<?php


namespace App\Order\Service\Order;

use App\Activity\Model\ActivityGoodsModel;
use App\Activity\Model\ActivityModel;
use App\Activity\Service\ActivityService;
use App\Activity\Service\Free\FreeMiniService;
use App\Activity\Service\Seckill\SeckillMiniService;
use App\Common\Constants\ErrorCode;
use App\Common\Service\BaseService;
use App\Common\Service\Random;
use App\Order\Model\EntrustOrderGoodsModel;
use App\Order\Model\EntrustOrderModel;
use App\Order\Model\FreeOrderRefund;
use App\Order\Model\KzRefundLogModel;
use App\Order\Model\OrderGoodsModel;
use App\Order\Model\OrderModel;
use App\Order\Model\WxRefundLogModel;
use App\Resource\Model\CategoryModel;
use App\Resource\Model\GoodsListModel;
use App\Resource\Service\CrdCartService;
use App\Resource\Service\GoodsService;
use App\Resource\Service\ShopService;
use App\Resource\Service\TeamLeaderService;
use App\User\Model\MemberModel;
use App\User\Service\MemberService;
use Carbon\Carbon;
use Hyperf\Database\Model\Builder;
use Hyperf\Database\Model\Model;
use Hyperf\Di\Annotation\Inject;
use App\Common\Constants\Stakeholder;
use Hyperf\Redis\RedisFactory;

class OrderMiniService extends OrderBaseService implements OrderServiceInterface
{

    /**
     * @Inject()
     * @var ActivityService
     */
    private $activityService;

    /**
     * @Inject()
     * @var FreeMiniService
     */
    private $freeMiniService;

    /**
     * @Inject()
     * @var SeckillMiniService
     */
    private $seckillMiniService;

    /**
     * @Inject()
     * @var GoodsService
     */
    private $goodsService;

    /**
     * @Inject()
     * @var MemberService
     */
    private $memberService;

    /**
     * @Inject()
     * @var ShopService
     */
    private $shopService;

    /**
     * 小程序个人订单角标
     * @param int $mid
     * @return array
     */
    public function orderCountSubscript(int $mid)
    {
        // 次日达待分享
        $iterator = null;
        $orderNoArr = [];
        $group_pay_share = '0';
        $redis = $this->groupRedis;
        while (false !== ($keys = $redis->scan($iterator, "share-{$mid}*"))) {
            foreach ($keys as $key) {
                $orderNoArr = array_merge($redis->sMembers($key), $orderNoArr);
            }
        }
        if (!empty($orderNoArr)) {
            $group_pay_share = (string)OrderModel::query()->where('mid', $mid)->whereIn('order_no', $orderNoArr)->count();
        }

        $field = [
            "SUM(IF(order_source=0 and status=1, 1, 0)) as pay_off_count",
            "SUM(IF(order_source=0 and status=2 and deal_type=1, 1, 0)) as pay_delivery",
            "SUM(IF(order_source=0 and status=3 and deal_type=1, 1, 0)) as pay_received",
            "SUM(IF(order_source=0 and status=3 and deal_type=2, 1, 0)) as pay_pick",
            "SUM(IF(order_source=1 and status=1, 1, 0)) as group_pay_off_count",
            "SUM(IF(order_source=1 and (status=3 or status=2), 1, 0)) as group_pay_pick"
        ];
        $res = OrderModel::query()
            ->selectRaw(implode(',', $field))
            ->where('mid', $mid)
            ->first()->toArray();
        $res['group_pay_share'] = $group_pay_share;
        return $res;
    }
    public function update(string $event='',array $where = [], array $update = [])
    {
        $order = $this->orderRepository->findFirst($where,['status','order_type']);
        $status = $order['status'];
        if($event=='cancel'&&$status !=self::ORDER_STATUS_1){
            return false;
        }
        if($event=='confirm'&&$status !=self::ORDER_STATUS_3){
            return false;
        }
        if($event=='cancel'&& $order['order_type']==self::ORDER_TYPE_10){
            $update['is_freed'] = 3;
        }
        return $this->orderRepository->update($where,$update);
    }

    public function delete()
    {
        // TODO: Implement delete() method.
    }

    public function info(string $order_no = ''){
        $order = OrderModel::query()->from('store_order as o')
            ->join('store_order_goods as g', 'g.order_no', '=', 'o.order_no')
            ->where(['o.order_no' => $order_no])
            ->select(['g.number', 'o.goods_price', 'o.total_price'])
            ->first();
        return $order?$order->toArray():[];
    }

    /**
     * 小程序-及时达订单列表
     * @param array $param
     * @param array $field
     */
    public function getTimelyOrderList(array $param=[], array $field = ['*'])
    {
        switch ($param['flag']) {
            case 0:
                // 全部
                $where = [
                    'order.mid' => $param['mid'],
                    'order.order_source' => Stakeholder::TIMELY_ORDER,
                ];
                break;
            case 1:
                //待支付
                $where = [
                    ['order.mid', '=', $param['mid']],
                    ['order.is_pay', '=', Stakeholder::ORDER_UNPAID],
                    ['order.status', '=', Stakeholder::ORDER_PENDING_PAYMENT],
                    ['order.order_source', '=', Stakeholder::TIMELY_ORDER]
                ];
                break;
            case 2:
                // 待发货
                $where = [
                    ['order.mid', '=', $param['mid']],
                    ['order.is_pay', '=', Stakeholder::ORDER_PAID],
                    ['order.status', '=', Stakeholder::ORDER_PENDING_SHIP],
                    ['order.deal_type', '=', Stakeholder::ORDER_DELIVERY],
                    ['order.order_source', '=', Stakeholder::TIMELY_ORDER]
                ];
                break;
            case 3:
                // 待收货
                $where = [
                    ['order.mid', '=', $param['mid']],
                    ['order.is_pay', '=', Stakeholder::ORDER_PAID],
                    ['order.status', '=', Stakeholder::ORDER_PENDING_PICK],
                    ['order.deal_type', '=', Stakeholder::ORDER_DELIVERY],
                    ['order.order_source', '=', Stakeholder::TIMELY_ORDER]
                ];
                break;
            case 4:
                // 待自提
                $where = [
                    ['order.mid', '=', $param['mid']],
                    ['order.is_pay', '=', Stakeholder::ORDER_PAID],
                    ['order.status', '=', Stakeholder::ORDER_PENDING_PICK],
                    ['order.deal_type', '=', Stakeholder::ORDER_SELF_PICK],
                    ['order.order_source', '=', Stakeholder::TIMELY_ORDER]
                ];
                $in = [
                    ['order.order_type', [Stakeholder::ORDER_TYPE_NORMAL, Stakeholder::ORDER_TYPE_NORMAL_SELF]],
                ];
                break;
            case 5:
                // 售后待处理
                $where = [
                    'refund.mid' => $param['mid'],
                    'refund.order_source' => Stakeholder::TIMELY_ORDER,
                    'refund.handle_type' => Stakeholder::REFUND_NOT_PROCESSED
                ];
                $field = [
                    'order.order_no',
                    'order.shop_id',
                    'refund.refund_money',
                    'refund.refund_no',
                    'refund.status',
                    'refund.handle_type',
                    'refund.create_at',
                ];
                return $this->orderRepository->miniCommonRefundOrderList($param, $where, $field);
                break;
            case 6:
                // 售后已处理
                $where = [
                    'refund.mid' => $param['mid'],
                    'refund.order_source' => Stakeholder::TIMELY_ORDER,
                    'refund.handle_type' => Stakeholder::REFUND_PROCESSED
                ];
                $field = [
                    'order.order_no',
                    'order.shop_id',
                    'refund.refund_money',
                    'refund.refund_no',
                    'refund.status',
                    'refund.handle_type',
                    'refund.create_at',
                ];
                return $this->orderRepository->miniCommonRefundOrderList($param, $where, $field);
                break;
            default:
        }
        return $this->orderRepository->miniCommonOrderList($param, $where, $field, $in ?? []);
    }

    /**
     * 删除购物车
     * @param $cartIds
     * @param $mid
     */
    public function delCart($cartIds,$mid)
    {
        $this->cartService->deleteCartById($cartIds,$mid);
    }
    /**
     * 小程序-次日达订单列表
     * @param array $param
     * @param array|string[] $field
     * @return Builder[]|\Hyperf\Database\Model\Collection|\Hyperf\Database\Query\Builder[]|\Hyperf\Utils\Collection
     */
    public function getNextDayOrderList(array $param, array $field = ['*'])
    {
        switch ($param['flag']) {
            case 0:
                // 全部
                $where = [
                    'order.mid' => $param['mid'],
                    'order.order_source' => Stakeholder::NEXT_DAY_ORDER,
                ];
                break;
            case 1:
                //待支付
                $where = [
                    ['order.mid', '=', $param['mid']],
                    ['order.is_pay', '=', Stakeholder::ORDER_UNPAID],
                    ['order.status', '=', Stakeholder::ORDER_PENDING_PAYMENT],
                    ['order.order_source', '=', Stakeholder::NEXT_DAY_ORDER]
                ];
                break;
            case 2:
                // 待分享
                $iterator = null;
                $orderNoArr = [];
                while (false !== ($keys = $this->groupRedis->scan($iterator, "share-{$param['mid']}*"))) {
                    foreach ($keys as $key) {
                        $orderNoArr = array_merge($this->groupRedis->sMembers($key), $orderNoArr);
                    }
                }
                // 订单号获取团号
                $groupNumArr = $this->groupRedis->hMGet('groupNum:orderNo', $orderNoArr);
                $where = [
                    'order.mid' => $param['mid'],
                ];
                $in = [['order.order_no', $orderNoArr]];
                break;
            case 3:
                // 待自提
                $where = [
                    ['order.mid', '=', $param['mid']],
                    ['order.is_pay', '=', Stakeholder::ORDER_PAID],
                    ['order.deal_type', '=', Stakeholder::ORDER_SELF_PICK],
                    ['order.order_source', '=', Stakeholder::NEXT_DAY_ORDER],
                    ['order.order_type_status', '!=', 0]
                ];
                $in = [
                    ['order.status', [Stakeholder::ORDER_PENDING_SHIP, Stakeholder::ORDER_PENDING_PICK]],
                ];
                break;
            case 4:
                // 已完成
                $where = [
                    'order.mid' => $param['mid'],
                    'order.status' => Stakeholder::ORDER_RECEIVED,
                    'order.order_source' => Stakeholder::NEXT_DAY_ORDER
                ];
                break;
            case 5:
                // 售后待处理和已处理
                $where = [
                    'order.mid' => $param['mid'],
                    'order.order_source' => Stakeholder::NEXT_DAY_ORDER
//                    'order.order_type' => Stakeholder::ORDER_TYPE_GROUP
                ];
                $in = [
                    ['refund.handle_type', [Stakeholder::REFUND_NOT_PROCESSED, Stakeholder::REFUND_PROCESSED]]
                ];
                $field = [
                    'order.order_no',
                    'order.shop_id',
                    'order.appointment_time',
                    'refund.refund_money',
                    'refund.refund_no',
                    'refund.status',
                    'refund.handle_type',
                    'refund.order_type',
                    'refund.create_at',
                ];
                return $this->orderRepository->miniCommonRefundOrderList($param, $where, $field, $in);
                break;
            default:
        }
        $list = $this->orderRepository->miniCommonOrderList($param, $where, $field, $in ?? []);
        if ($param['flag'] == 2) {
            foreach ($list as $k => $v) {
                $list[$k]['groupNumber'] = $groupNumArr[$v['order_no']];
            }
        }
        if ($param['flag'] == 3 || $param['flag'] == 4) {
            if (isset($param['perpage']) && !empty($param['perpage'])) {
                $items = $list->items();
            } else {
                $items = $list->toArray();
            }
            $orderNoArr = array_column($items, 'order_no');
            $groupNumArr = $this->groupRedis->hMGet('groupNum:orderNo', $orderNoArr);
            foreach ($list as $k => $v) {
                $groupMemb = $this->groupRedis->zRange((string)$groupNumArr[$v['order_no']], 0, -1);
                $avatar = [];
                if (!empty($groupMemb)) {
                    foreach ($groupMemb as $kk => $vv) {
                        array_push($avatar, json_decode($vv, true)['avatar']);
                    }
                    $list[$k]['avatar'] = $avatar;
                }
                if (empty($avatar)) {
                    $list[$k]['avatar'] = [$v['member']['face_url']];
                }
                unset($v['member']);
            }
        }
        return $list;
    }

    /**
     * 小程序-订单详情
     * @param array $where
     * @param array|string[] $field
     * @return Builder|Model|\Hyperf\Database\Query\Builder|object|null
     */
    public function orderDetail(array $where, array $field = ['*'])
    {

        $detail = $this->orderRepository->orderDetail($where,$field);
        if (!$detail) return $detail;
        if ($detail->deal_type == Stakeholder::ORDER_DELIVERY) {
            $addressInfo = $this->memberService->getAddressInfo(['id' => $detail->address_id],['id as address_id', 'phone', 'username', 'area', 'address','gender']);
            $detail->receive_address = $addressInfo['area'] . $addressInfo['address'];
            $detail->receive_username = $addressInfo['username'];
            $detail->receive_phone = $addressInfo['phone'];
            $detail->gender = $addressInfo['gender'];
        }
        if ($detail->order_type == Stakeholder::ORDER_TYPE_FREE){
            $gpk = GoodsListModel::query()->where('goods_id', $detail->goods->toArray()[0]['goods_id'])->value('goods_pick_time');
            $takeDate = $this->getOverNightTakeDate();
            foreach ($detail->goods as $v) $v['goods_pick_time'] = $takeDate . ' ' . substr($gpk, 0, 5);

            $detail->free_step = $detail->is_pay == 0 ? 0: $detail->free_step;
            $act = ActivityModel::query()->where('activityID',$detail->activity_id)->first(['end_date','activity_prams']);
            $activity_prams = json_decode($act->activity_prams, true);
            $detail->share_image = $activity_prams['share_image'];
            $detail->share_text = $activity_prams['share_text'];
            $invite = $this->freeInviteDetail($detail);//邀请好友
            $detail->invite = $invite;
            $detail->free_result = $this->freeResultDetail($detail, $invite, $act);// 免单成功
        }
        return $detail;
    }
    /**
     * 小程序-拼团订单详情
     * @param array $param
     * @param array $where
     * @param array $field
     * @return Builder|\Hyperf\Database\Model\Model|object|null
     */
    public function getGroupOrderDetail(array $where, array $field, ?array $param)
    {
        // 获取团号
        $group = $this->activityService->getGroupInfoByGroupNum((string)$this->groupRedis->hGet("groupNum:orderNo", (string)$param['order_no']));

        $detail =$this->orderRepository->orderDetail($where,$field);
        if ($detail->deal_type == Stakeholder::ORDER_DELIVERY) {
            $addressInfo = $this->memberService->getAddressInfo(['id' => $detail->address_id], ['id as address_id', 'phone', 'username', 'area', 'address', 'gender']);
            $detail->receive_address = $addressInfo['area'] . $addressInfo['address'];
            $detail->receive_username = $addressInfo['username'];
            $detail->receive_phone = $addressInfo['phone'];
            $detail->gender = $addressInfo['gender'];
        }
        $detail['group'] = $group['data'] ?? "";
        return $detail;
    }

    /**
     * 及时达写入订单
     * @param array $cartList
     * @param array $param
     * @param int $shop_id
     * @return array
     * @author lulongfei
     */
    public function saveOrder(array $cartList, array $param, int $shop_id)
    {
        $orderGoodsMoney = $orderGoodsNum = 0;
        foreach ($cartList as $k => $v) {
            if($v['price_selling']<=0){
                return ['code' => ErrorCode::GOODS_SELL_OUT, 'msg' => '商品信息异常'];
            }
            if($v['group_id']==Stakeholder::GROUP_ID_2 && $param['pay_type']==Stakeholder::PAYMENT_METHOD_WECHAT){
                return ['code' => ErrorCode::ORDER_PAY_TYPE_ERROE, 'msg' => '会员商品只能选择余额支付'];
            }
            $orderGoodsMoney += bcmul((string)$cartList[$k]['goods_num'], (string)($cartList[$k]['price_selling'] * 100), 2);
            $orderGoodsNum += $cartList[$k]['goods_num'];
        }
        if (!empty($param['coupon'])) {
            if (empty($param['payKey'])) {
                return ['code' => ErrorCode::SYSTEM_INVALID, 'msg' => '缺少payKey参数'];
            }
            $coupon = json_decode($param['coupon'], true);
            $cut = (float)array_sum(array_column($coupon, 'deductMoney')); // 优惠的总金额 单位分
            $coupon_info = json_encode(['payKey' => $param['payKey'], 'coupon' => $param['coupon']]);
            $coupon_status = 1;

            // 使用运费券的情况
            $couponFreight = [];
            foreach ($coupon as $k => $v) {
                // 运费券
                if ($v['apply_type'] == 4) {
                    array_push($couponFreight, $v);
                }
            }
            if (!empty($couponFreight) && $param['deal_type'] == self::ORDER_DEAL_TYPE_1) {
                // 优惠的运费金额
                $coupon_freight_cut = (float)array_sum(array_column($couponFreight, 'deductMoney'));//单位分
                $coupon_freight = json_encode($couponFreight);
                $goods_cut = bcsub((string)$cut, (string)$coupon_freight_cut, 2); // 商品优惠金额
                $orderGoodsMoney = bcsub((string)$orderGoodsMoney, (string)$goods_cut, 2);
                // 运费是否优惠完
                $freight_price = bcsub((string)($param['freight_price'] * 100), (string)$coupon_freight_cut, 2);
                $totalPrice = bcadd((string)$orderGoodsMoney, (string)$freight_price, 2);
            } else {
                // 没有运费券, 优惠的总金额就是商品优惠金额
                $orderGoodsMoney = bcsub((string)$orderGoodsMoney, (string)$cut, 2);
                $totalPrice = $param['deal_type'] == self::ORDER_DEAL_TYPE_1 ? bcadd((string)$orderGoodsMoney, (string)($param['freight_price'] * 100), 2) : $orderGoodsMoney;
            }
        } else {
            $totalPrice = $param['deal_type'] == self::ORDER_DEAL_TYPE_1 ? bcadd((string)$orderGoodsMoney, (string)($param['freight_price'] * 100), 2) : $orderGoodsMoney;
        }
        if (bccomp((string)($param['total_price'] * 100), (string)$totalPrice, 2)) {
            return ['code' => ErrorCode::ORDER_PRICE_ERROR];
        }
        /***************************************************************************************/

        $orderNo = self::generateOrderNo($shop_id);
        $orderGoodsInsertData = $orderExpressInsertData = [];
        $userInfo = $this->memberService->findFirst(['mid' => $param['mid']],['mid', 'openid', 'phone']);
        $datetime = date('Y-m-d H:i:s');
        preg_match("/[0-9]{1,}:[0-9]{1,}/",$param['appointment_time'],$match);
        $appointment_date = $match?date('Y-m-d ').$match[0]:'';
        $orderData = [
            'mid' => $userInfo['mid'],
            'openid' => $userInfo['openid'],
            'order_phone' => $userInfo['phone'],
            'order_no' => $orderNo,
            'activity_id' => $param['activity_id'] ?? 0,
            'activity_type' => $param['activity_type'] ?? 0,
            'shop_id' => $shop_id,
            'deal_type' => $param['deal_type'],
            'goods_price' => bcdiv((string)$orderGoodsMoney, '100', 2),
            'freight_price' => $param['deal_type'] == self::ORDER_DEAL_TYPE_1 ? ($param['freight_price'] ?? 0.00) : 0.00,
            'total_price' => bcdiv((string)$totalPrice, '100', 2),
            'pay_type' => $param['pay_type'],
            'memo' => $param['memo'],
            'order_goods_num' => $orderGoodsNum,
            'order_type' => $param['order_type'],
            'appointment_time' => $param['appointment_time'],
            'appointment_date' => $appointment_date,
            'order_source' => $param['order_source'] ?? 0,
            'order_type_status' => $param['order_type'] == self::ORDER_TYPE_0 ? 0 : ($param['order_type'] == self::ORDER_TYPE_2 ? 2 : 0),
            'serial_num' => $this->orderRepository::getToDayOrderSerialNumByShopId($shop_id),
            'create_at' => $datetime,
            'coupon_info' => $coupon_info ?? '', // 券码
            'coupon_cut' =>  isset($cut) && !empty($cut)  ?bcdiv((string)$cut, '100', 2):0,          // 优惠金额
            'coupon_status' => $coupon_status ?? 0,  //是否使用优惠券,0未使用,1使用
            'coupon_freight' => isset($coupon_freight) && !empty($coupon_freight) ? bcdiv((string)$coupon_freight, '100', 2) : '',
            'coupon_freight_cut' => isset($coupon_freight_cut) && !empty($coupon_freight_cut) ? bcdiv((string)$coupon_freight_cut, '100', 2) : 0

        ];
        if ($param['deal_type'] == self::ORDER_DEAL_TYPE_1) {
            $orderData['address_id'] = $param['address_id'];
            $orderExpressInsertData = [
                'mid' => $userInfo['mid'],
                'shop_id' => $param['shop_id'],
                'order_no' => $orderNo,
                'create_at' => $datetime,
            ];
        } else {
            $writeOffCode = Random::character(8);
            $orderData['write_off_code'] = $writeOffCode;
        }
        $goodsIds = array_column($cartList, 'goods_id');
        $goodsList = $this->goodsService->getGoodsLsy($goodsIds,['id', 'wx_crm_code', 'kz_goods_id', 'kz_type_id', 'cate_id', 'crd_cate_id', 'lsy_goods_name', 'lsy_unit_name', 'lsy_class_name']);
        $goodsListById = array_column($goodsList, null, 'id');

        foreach ($cartList as $arr) {
            $kz_goods_id = !empty($goodsListById[$arr['goods_id']]['kz_goods_id']) ? $goodsListById[$arr['goods_id']]['kz_goods_id'] : $arr['goods_id'];
            $orderGoodsInsertData[] = [
                'mid' => $userInfo['mid'],
                'shop_id' => $param['shop_id'],
                'order_no' => $orderNo,
                'goods_id' => $arr['goods_id'],
                'cate_id' =>$goodsListById[$arr['goods_id']]['cate_id'] ?? 0,
                'activity_goods_id' => $arr['activity_goods_id'],
                'itemCode' => $goodsListById[$arr['goods_id']]['wx_crm_code'] ?? 0,
                'kz_goods_id' => $kz_goods_id,
                'kz_type_id' => $goodsListById[$arr['goods_id']]['kz_type_id'] ?? 0,
                'group_id' => $arr['group_id'],
                'goods_title' => $arr['title'],
                'goods_spec' => $arr['goods_spec'],
                'goods_logo' => $arr['logo'],
                'selling_price' => $arr['price_selling'],
                'market_price' => $arr['price_market'],
                'number' => $arr['goods_num'],
                'crd_cate_id'=>$goodsListById[$arr['goods_id']]['crd_cate_id']??0,
                'lsy_goods_name'=>$goodsListById[$arr['goods_id']]['lsy_goods_name'],
                'lsy_unit_name'=>$goodsListById[$arr['goods_id']]['lsy_unit_name'],
                'lsy_class_name'=>$goodsListById[$arr['goods_id']]['lsy_class_name'],
                'create_at' => $datetime,
                'kz_self_num'=> $arr['kz_self_num']
            ];
        }
        $res =  $this->orderRepository->saveOrder((int)$param['mid'],$orderData,$orderGoodsInsertData,$param,self::ORDER_SOURCE_0,$orderNo,$orderExpressInsertData,array_column($cartList,'cart_id'));
        return $res;
    }

    /**
     * 次日达订单写入
     * @param array $cartGoodsArr
     * @param array $param
     * @param array $goodsInfo
     * @param array $goodsIdsArr
     * @return array
     * @author lulongfei
     */
    public function saveOrderTomorrow(array $cartList, array $param, int $shop_id)
    {
        $orderGoodsMoney = $orderGoodsNum = $commission=0;
        $orderType = self::ORDER_TYPE_8;
        $activity_id = 0;
        $activityType =0;
        foreach ($cartList as $arr) {
            if($arr['group_id']==Stakeholder::GROUP_ID_4){
                $orderType = self::ORDER_TYPE_9;
            }
            if ($arr['price_selling'] <= 0) {
                return ['code' => ErrorCode::GOODS_SELL_OUT, 'msg' => '商品信息异常:'.$arr['title']];
            }
            $orderGoodsMoney += bcmul((string)$arr['goods_num'], (string)($arr['price_selling']*100), 2);
            $commission +=$arr['commission']? bcmul((string)$arr['goods_num'], (string)($arr['commission']*100), 2):0;
            $orderGoodsNum += $arr['goods_num'];
        }

        $coupon_status = 0;
        $coupon_info = '';
        $cut =0;
        if (!empty($param['coupon'])) {
            if (empty($param['payKey'])) {
                return ['code' => ErrorCode::SYSTEM_INVALID, 'msg' => '缺少payKey参数'];
            }
            $coupon = json_decode($param['coupon'], true);
            $cut = (float) array_sum(array_column($coupon, 'deductMoney'));
            // 优惠的总金额 单位分
            $coupon_info = json_encode(['payKey' => $param['payKey'], 'coupon' => $param['coupon']]);
            $coupon_status = 1;
            $orderGoodsMoney = bcsub((string)$orderGoodsMoney, (string)$cut, 2);
        }
        $totalPrice = $orderGoodsMoney;
        if (bccomp((string)($param['total_price'] * 100), (string)$totalPrice, 2)) {
            return ['code' => ErrorCode::ORDER_PRICE_ERROR];
        }

        /***************************************************************************************/

        $orderNo = self::generateOrderNo($shop_id);
        $orderGoodsInsertData = [];
        $userInfo = $this->memberService->findFirst(['mid' => $param['mid']],['mid', 'openid', 'phone']);
        $datetime = date('Y-m-d H:i:s');
        preg_match("/[0-9]{1,}-[0-9]{1,}\s[0-9]{1,}:[0-9]{1,}/",$param['appointment_time'],$match);
        $appointment_date =$match? date('Y-').$match[0]:'';
        $orderData = [
            'mid' => $userInfo['mid'],
            'openid' => $userInfo['openid'],
            'order_phone' => $userInfo['phone'],
            'order_no' => $orderNo,
            'activity_id' => $activity_id,
            'activity_type' => $activityType,
            'shop_id' => $shop_id,
            'deal_type' => self::ORDER_TYPE_2,
            'goods_price' => bcdiv((string)$totalPrice, '100', 2),
            'total_price' => bcdiv((string)$totalPrice, '100', 2),
            'pay_type' => $param['pay_type'],
            'memo' => $param['memo'],
            'order_goods_num' => $orderGoodsNum,
            'order_type' => $orderType,
            'appointment_time' => $param['appointment_time'],
            'appointment_date' => $appointment_date,
            'order_source' => self::ORDER_SOURCE_1,//次日达
            'order_type_status' => 2,
            'serial_num' => $this->orderRepository::getToDayOrderSerialNumByShopId($shop_id),
            'create_at' => $datetime,
            'coupon_info' => $coupon_info, // 券码
            'coupon_cut' => $cut?bcdiv((string)$cut, '100', 2):0,          // 优惠金额
            'coupon_status' => $coupon_status,  //是否使用优惠券,0未使用,1使用
            'coupon_freight' => '',
            'coupon_freight_cut' => 0,
            'order_commission' => bcdiv((string)$commission, '100', 2),
            'leader_id' => $param['leader_id']?? 0,
            'platform_type' => $param['leader_id']?2: 1

        ];

        $writeOffCode = Random::character(8);
        $orderData['write_off_code'] = $writeOffCode;
        $goodsIds = array_column($cartList, 'goods_id');

        $goodsList = $this->goodsService->getGoodsLsy($goodsIds,['id', 'wx_crm_code', 'kz_goods_id', 'kz_type_id', 'cate_id', 'crd_cate_id', 'lsy_goods_name', 'lsy_unit_name', 'lsy_class_name']);
        $goodsListById = array_column($goodsList, null, 'id');
        foreach ($cartList as $arr) {
            $kz_goods_id = !empty($goodsListById[$arr['goods_id']]['kz_goods_id']) ? $goodsListById[$arr['goods_id']]['kz_goods_id'] : $arr['goods_id'];
            $orderGoodsInsertData[] = [
                'mid' => $userInfo['mid'],
                'shop_id' => $param['shop_id'],
                'order_no' => $orderNo,
                'goods_id' => $arr['goods_id'],
                'cate_id' => $goodsListById[$arr['goods_id']]['cate_id'] ?? 0,
                'activity_goods_id' => $arr['activity_goods_id'],
                'activity_id' => $arr['activityID']??0,
                'itemCode' => $goodsListById[$arr['goods_id']]['wx_crm_code'] ?? 0,
                'kz_goods_id' => $kz_goods_id,
                'kz_type_id' => $goodsListById[$arr['goods_id']]['kz_type_id'] ?? 0,
                'group_id' => $arr['group_id'],
                'goods_title' => $arr['title'],
                'goods_spec' => $arr['goods_spec'],
                'goods_logo' => $arr['logo'],
                'selling_price' => $arr['price_selling'],
                'market_price' => $arr['price_market'],
                'cost_price' => $arr['cost_price'] ?? 0.00,
                'number' => $arr['goods_num'],
                'commission' => $arr['commission'] ?? 0,
                'crd_cate_id'=>$goodsListById[$arr['goods_id']]['crd_cate_id'],
                'lsy_goods_name'=>$goodsListById[$arr['goods_id']]['lsy_goods_name'],
                'lsy_unit_name'=>$goodsListById[$arr['goods_id']]['lsy_unit_name'],
                'lsy_class_name'=>$goodsListById[$arr['goods_id']]['lsy_class_name'],
                'create_at' => $datetime,
                'kz_self_num'=>$arr['kz_self_num']
            ];
        }
        $res =  $this->orderRepository->saveOrder((int)$param['mid'],$orderData,$orderGoodsInsertData,$param,self::ORDER_SOURCE_1,$orderNo,[],array_column($cartList,'cart_id'));
        return $res;
    }
    /**
     * 活动立即购买订单写入
     * @param array $param
     * @return array
     * @author lulongfei
     */
    public function saveActivityOrder(array $param)
    {
        $shop_id = $param['shop_id'];
        $goodsByActivity = $this->activityService->getActivityGoodsInfo((int)$param['activityID'], (int)$shop_id);
        if (empty($goodsByActivity)) {
            return ['code' => ErrorCode::GOODS_INVALID];
        }
        if($goodsByActivity['end_date']<time()){
            return ['code' => ErrorCode::GOODS_INVALID,'msg'=>'抱歉，该活动已结束！'];
        }
        if ($goodsByActivity['price_selling'] <= 0) {
            return ['code' => ErrorCode::GOODS_SELL_OUT, 'msg' => '商品信息异常'];
        }
        $num = $param['num'] ?? 1;
        if ($num > $goodsByActivity['stock']) {
            return ['code' => ErrorCode::GOODS_SELL_OUT];
        }
        $goods_price = $goodsByActivity['price_selling'];
        if ($param['activity_type']) {
            $goods_price = $param['activity_type'] == 1 ? $goodsByActivity['costprice'] : $goodsByActivity['price_selling'];
        }

        $orderGoodsMoney = bcmul((string)$num, (string)$goods_price, 2);
        $orderCommission= $goodsByActivity['commission']?bcmul((string)$num, (string)$goodsByActivity['commission'], 2):0.00;
        $totalPrice = $orderGoodsMoney;
        $orderNo = self::generateOrderNo($shop_id);
        $userInfo = $this->memberService->findFirst(['mid' => $param['mid']],['mid', 'openid', 'phone']);
        $datetime = date('Y-m-d H:i:s');
        preg_match("/[0-9]{1,}-[0-9]{1,}\s[0-9]{1,}:[0-9]{1,}/",$param['appointment_time'],$match);
        $appointment_date =$match? date('Y-').$match[0]:'';
        $orderData = [
            'mid' => $userInfo['mid'],
            'openid' => $userInfo['openid'],
            'order_phone' => $userInfo['phone'],
            'order_no' => $orderNo,
            'activity_id' => $goodsByActivity['activityID'] ?? 0,
            'activity_type' => $param['activity_type'] ?? 0,
            'shop_id' => $shop_id,
            'deal_type' => self::ORDER_DEAL_TYPE_2,
            'goods_price' => $orderGoodsMoney,
            'total_price' => $totalPrice,
            'pay_type' => $param['pay_type'],
            'memo' => $param['memo'],
            'order_goods_num' => $num,
            'order_type' => $param['order_type'],
            'appointment_time' => $param['appointment_time'],
            'appointment_date' => $appointment_date,
            'order_source' => self::ORDER_SOURCE_1,//次日达
            'order_type_status' => 2,
            'serial_num' => $this->orderRepository::getToDayOrderSerialNumByShopId($shop_id),
            'create_at' => $datetime,
            'coupon_info' => '', // 券码
            'coupon_cut' => 0,          // 优惠金额
            'coupon_status' => 0,  //是否使用优惠券,0未使用,1使用
            'coupon_freight' => '',
            'coupon_freight_cut' => 0,
            'order_commission' => $orderCommission ?? 0,
            'leader_id' => $param['leader_id']?? 0,
            'platform_type' => $param['leader_id']?2: 1
        ];
        $writeOffCode = Random::character(8);
        $orderData['write_off_code'] = $writeOffCode;
        $goods = $this->goodsService->getGoodsLsy([$goodsByActivity['goods_id']],['id', 'wx_crm_code', 'kz_goods_id', 'kz_type_id', 'cate_id', 'crd_cate_id', 'lsy_goods_name', 'lsy_unit_name', 'lsy_class_name'])[0];
        $kz_goods_id = !empty($goods['kz_goods_id']) ? $goods['kz_goods_id'] : $goodsByActivity['goods_id'];
        $orderGoodsInsertData = [
            'mid' => $userInfo['mid'],
            'shop_id' => $param['shop_id'],
            'order_no' => $orderNo,
            'goods_id' => $goodsByActivity['goods_id'],
            'cate_id' => $goodsByActivity['cate_id'] ?? 0,
            'activity_goods_id' => $goodsByActivity['activity_goods_id'],
            'itemCode' => $goods['wx_crm_code'] ?? 0,
            'kz_goods_id' => $kz_goods_id,
            'kz_type_id' => $goods['kz_type_id'] ?? 0,
            'group_id' => $goodsByActivity['group_id'],
            'goods_title' => $goodsByActivity['goods_title'],
            'goods_spec' => $goodsByActivity['goods_spec'],
            'goods_logo' => $goodsByActivity['image'],
            'selling_price' => $goods_price,
            'market_price' => $goodsByActivity['costprice'] ?? 0.00,
            'cost_price' => $goodsByActivity['current_cost_price'] ?? 0.00,
            'number' => $num,
            'commission' => $goodsByActivity['commission'] ?? 0,
            'crd_cate_id'=>$goods['crd_cate_id'] ?? 0,
            'lsy_goods_name'=>$goods['lsy_goods_name'],
            'lsy_unit_name'=>$goods['lsy_unit_name'],
            'lsy_class_name'=>$goods['lsy_class_name'],
            'create_at' => $datetime,
            'kz_self_num'=>'xp'.Random::character(8)
        ];
        $res =  $this->orderRepository->saveOrder((int)$param['mid'],$orderData,$orderGoodsInsertData,$param,self::ORDER_SOURCE_1,$orderNo);
        return $res;
    }
    /**
     * 及时达确认订单
     * @param $param
     * @return array
     * @author lulongfei
     */
    public function confirmOrder($param){
        $shop_id = (int)$param['shop_id'];
        $result = $this->shopService->getShopCondition($shop_id, (int)$param['order_type'],(int)$param['deal_type'],(int) $param['address_id']);
        if ($result['code']) {
            return $this->error($result['code']);
        }
        $cart = $this->cartService->checkCart((int)$param['mid'],$shop_id,self::CART_SOURCE_1);
        if ($cart['code']) {
            return $this->error($cart['code']);
        }
        $cartList = $cart['cartList'];
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        //及时达普通商品
        $res = $this->checkCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];
        //及时达限购商品
        $quota = $this->checkCartGoodsQuota($shop_id,$cartList,(int)$param['mid'],$redis);
        $quotaCartList = $quota['cartList'];
        $cartList = array_merge($generalCartList,$quotaCartList);
        if (empty($cartList)) {
            return $this->error(ErrorCode::CART_NULL);
        }
        $res = $this->saveOrder($cartList, $param,$shop_id);
        return $res;
    }
    /**
     * 次日达确认订单
     * @param $param
     * @return array
     * @author lulongfei
     */
    public function confirmOrderTomorrow($param){
        $shop_id = (int)$param['shop_id'];
        $mid = (int)$param['mid'];
        if(!$this->shopService->getShopInfobyShopIds([$shop_id],['shop_id'])->toArray()){
            return $this->error(ErrorCode::SHOP_STATUS_CLOSE);
        }
        $cart = $this->cartService->checkCart($mid,$shop_id,self::CART_SOURCE_2);
        if ($cart['code']) {
            return $this->error($cart['code']);
        }
        $cartList = $cart['cartList'];

        $redis = $this->container->get(RedisFactory::class)->get('resource');
        $res = $this->checkCrdCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];

        foreach ($generalCartList as $k => $v) {
            $cartRes = CrdCartService::is_overflow($generalCartList[$k]['goods_num'],$mid,$generalCartList[$k]['goods_id']);
            if($cartRes){
                return $this->error(30005,$generalCartList[$k]['title'].'每人每天限购'.$generalCartList[$k]['limite_num_per_day'].''.'件');//每人每天限购
            }
            if(empty($generalCartList[$k]['goods_num'])){
                return $this->error(ErrorCode::GOODS_SELL_OUT_PART, '商品信息异常:'.$v['title']);
            }
        }
        $seckill = $this->checkCrdCartGoodsSeckill($shop_id,$cartList,$mid,$redis);
        $seckillCartList = $seckill['cartList'];
        $cartList = array_merge($seckillCartList,$generalCartList);
        if (empty($cartList)) {
            return $this->error(ErrorCode::CART_NULL);
        }
        $res = $this->saveOrderTomorrow($cartList, $param,$shop_id);
        return $res;
    }
    /***
     *
     * 及时达 获取确认订单数据
     * @param array $param
     * @return array
     * @author lulongfei
     */
    public function getConfirmOrderInfo(array $param){
        $shop_id = (int)$param['shop_id'];
        $mid = (int)$param['mid'];
        $cart = $this->cartService->checkCart($mid,$shop_id,self::CART_SOURCE_1);
        if ($cart['code']) {
            return $this->error($cart['code']);
        }
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        $cartList = $cart['cartList'];
        //及时达普通商品
        $res = $this->checkCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];
        $generalSellOutGoodsTitle = $res['sellOutGoodsTitle'];
        //及时达限购商品
        $quota = $this->checkCartGoodsQuota($shop_id,$cartList,$mid,$redis);
        $quotaCartList = $quota['cartList'];
        $quotaSellOutGoodsTitle = $quota['sellOutGoodsTitle'];
        $cartList = array_merge($generalCartList,$quotaCartList);
        $goodsTotalMoney = $goodMarketTotalMoney = $goodsNum = 0;
        foreach ($cartList as $k => $v) {
            $goodMarketTotalMoney += bcmul((string)$cartList[$k]['goods_num'], (string)($cartList[$k]['price_market'] * 100), 2);
            $goodsTotalMoney += bcmul((string)$cartList[$k]['goods_num'], (string)($cartList[$k]['price_selling'] * 100), 2);
            $goodsNum += $cartList[$k]['goods_num'];
        }

        $sellOutGoodsTitle = array_merge($quotaSellOutGoodsTitle,$generalSellOutGoodsTitle);
        if(empty($cartList)&&empty($sellOutGoodsTitle)){
            return $this->error(ErrorCode::CART_NULL);
        }
        //获取店铺配送信息
        $deliverArr = $this->shopService->getDeliver($shop_id);
        $addressMemArr = $this->memberService->getAddressInfo(['mid' => $mid, 'is_default' => 1,'is_deleted'=>0],['id as address_id', 'phone', 'username', 'area', 'address']);
        //获取运费(配送方式：(1配送订单,2为自提订单)
        if ($param['deal_type'] == 1) {
            if ($goodsTotalMoney >= $deliverArr['free_deliver_money'] * 100) {
                $shop_freight = 0;
            } else {
                $shop_freight = $deliverArr['shop_freight'];
            }
        } else {
            $shop_freight = 0;
        }
        // 拼团人数团信息
        $activity_type = 0;
        $groupNum = 0;
        $shopInfo = $this->shopService->getInfoByShopId($shop_id, ['shop_id', 'shop_name', 'address', 'shop_tel', 'shop_desc','longitude','latitude']);
        $data = [
            'activity_type' => $activity_type,
            'groupNum' => $groupNum,
            'deliver_info' => $deliverArr,
            'member_address' => $addressMemArr ?? [],
            'shop_info' => $shopInfo,
            'goods_list' => $cartList,
            'goods_num' => $goodsNum,
            'shop_freight' => $shop_freight,
            'peckTime'=>[
                'week'=>self::get_weeks(1),
                'pick_date'=>$this->getTodayPickTime(),
                'match_date'=>$this->getTodayDeliverTime()
            ],
            'GoodsTotalMoney' => bcdiv((string)$goodsTotalMoney, '100', 2),
            'TotalMoney' => bcdiv(bcadd((string)$goodsTotalMoney, (string)($shop_freight * 100), 2), '100', 2),
            'sellOutGoodsTitle' => $sellOutGoodsTitle
        ];

        return $this->success($data);
    }
    /**
     * 代客下单模板过期时间判断
     *
     * @param string $timestamp
     * @return bool
     */
    public function checkEntrustTime($timestamp = ''): bool
    {
        $nowTime = time();

        if($nowTime > $timestamp){
            return false;
        }
        return true;
    }

    protected function getEntrustExpTime($param)
    {
        $expTime = json_decode($param, true);
        $url = $expTime['path'];
        $arr = parse_url($url);
        return $this -> convertUrlQuery($arr['query'])['exp'];
    }

    /**
     * 代客下单及时达确认订单
     * @param array $param
     * @return array
     */
    public function getJsdEntrustOrderInfo(array $param): array
    {
        $mid = (int)$param['mid'];
        $entrustInfo = EntrustOrderModel::query()
            -> where('id', $param['entrust_id'])
            -> first(['id', 'shop_id', 'amount', 'dis_amount', 'discount', 'status', 'share', 'order_source', 'created_at']);
        if(!$entrustInfo) return ['code' => ErrorCode::NOT_EXIST];
        $expTime = $this -> getEntrustExpTime($entrustInfo -> share);
        $checkTime = $this -> checkEntrustTime($expTime);
        if(!$checkTime){
            return ['code'  => ErrorCode::LINK_EXPIRED];
        }
        $goodsInfo = EntrustOrderGoodsModel::query() -> where('entrust_order_id', $entrustInfo -> id) -> get() -> toArray();
        foreach($goodsInfo as $key => $val){
            $goodsInfo[$key]['goods_num'] = $val['number'];
        }
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        $cartList = $goodsInfo;
        $shop_id = $entrustInfo -> shop_id;
        //及时达普通商品
        $res = $this->checkCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];
        $generalSellOutGoodsTitle = $res['sellOutGoodsTitle'];
        //及时达限购商品
        $quota = $this->checkCartGoodsQuota($shop_id,$cartList,$mid,$redis);
        $quotaCartList = $quota['cartList'];
        $quotaSellOutGoodsTitle = $quota['sellOutGoodsTitle'];
        $cartList = array_merge($generalCartList,$quotaCartList);
        $goodsTotalMoney = $goodMarketTotalMoney = $goodsNum = $discountClassPrice = 0;
        foreach ($cartList as $k => $v) {
            $cartList[$k]['price_selling'] = $cartList[$k]['dis_unit_price'];
            $goodMarketTotalMoney += bcmul((string)$cartList[$k]['goods_num'], (string)($cartList[$k]['price_market'] * 100), 2);  // 商品市场价
            $goodsTotalMoney += bcmul((string)$cartList[$k]['subtotal'], '100', 2); // 商品未优惠合计
            $discountClassPrice += bcsub((string)$cartList[$k]['subtotal'] * 100, (string)$cartList[$k]['dis_subtotal'] * 100, 2); // 商品优惠
            $goodsNum += $cartList[$k]['goods_num'];
        }
        $goodsDiscountPrice = bcdiv((string)bcsub((string)$goodsTotalMoney, (string)$discountClassPrice, 2), '100', 2);   // 商品优惠后金额（元）
        $sellOutGoodsTitle = array_merge($quotaSellOutGoodsTitle,$generalSellOutGoodsTitle);
        if(empty($cartList)&&empty($sellOutGoodsTitle)){
            return $this->error(ErrorCode::ENTRUST_NULL);
        }
        //获取店铺配送信息
        $deliverArr = $this->shopService->getDeliver($shop_id);
        $addressMemArr = $this->memberService->getAddressInfo(['mid' => $mid, 'is_default' => 1,'is_deleted'=>0],['id as address_id', 'phone', 'username', 'area', 'address']);
        //获取运费(配送方式：(1配送订单,2为自提订单)
        if ($param['deal_type'] == 1) {
            if ($goodsDiscountPrice * 100 >= $deliverArr['free_deliver_money'] * 100) {
                $shop_freight = 0;
            } else {
                $shop_freight = $deliverArr['shop_freight'];
            }
        } else {
            $shop_freight = 0;
        }
        // 拼团人数团信息
        $activity_type = 0;
        $groupNum = 0;
        $shopInfo = $this->shopService->getInfoByShopId($shop_id, ['shop_id', 'shop_name', 'address', 'shop_tel', 'shop_desc','longitude','latitude']);
        $data = [
            'activity_type' => $activity_type,
            'groupNum' => $groupNum,
            'deliver_info' => $deliverArr,
            'member_address' => $addressMemArr ?? [],
            'shop_info' => $shopInfo,
            'goods_list' => $cartList,
            'goods_num' => $goodsNum,
            'shop_freight' => $shop_freight,
            'peckTime'=>[
                'week'=>self::get_weeks(1),
                'pick_date'=>$this->getTodayPickTime(),
                'match_date'=>$this->getTodayDeliverTime()
            ],
            'GoodsTotalMoney' => bcdiv((string)$goodsTotalMoney, '100', 2), // 商品总金额（未优惠）
            'TotalMoney' => bcdiv((string)bcadd((string)($goodsDiscountPrice * 100), (string)($shop_freight * 100), 2), '100', 2),
            'sellOutGoodsTitle' => $sellOutGoodsTitle,
            'amount' => bcdiv((string)$goodsTotalMoney, '100', 2), // 商品总金额
            'dis_amount' => $goodsDiscountPrice,
            'discount' => $entrustInfo -> discount,
            'share' => $entrustInfo -> share,
            'status' => $entrustInfo -> status,
        ];
        return ['code'  => ErrorCode::SUCCESS, 'data'  => $data];
    }

    /**
     * 代客下单次日达确认订单
     * @param array $param
     * @return array
     */
    public function getCrdEntrustOrderInfo(array $param): array
    {
        $mid = (int)$param['mid'];
        $entrustInfo = EntrustOrderModel::query()
            -> where('id', $param['entrust_id'])
            -> first(['id', 'shop_id', 'amount', 'dis_amount', 'discount', 'status', 'share', 'order_source', 'created_at']);
        $param['shop_id'] = $entrustInfo -> shop_id;
        if(!$entrustInfo) return ['code' => ErrorCode::NOT_EXIST];
        $expTime = $this -> getEntrustExpTime($entrustInfo -> share);
        $checkTime = $this -> checkEntrustTime($expTime);
        if(!$checkTime){
            return ['code'  => ErrorCode::LINK_EXPIRED];
        }
        $goodsInfo = EntrustOrderGoodsModel::query() -> where('entrust_order_id', $entrustInfo -> id) -> get() -> toArray();
        foreach($goodsInfo as $key => $val){
            $goodsInfo[$key]['goods_num'] = $val['number'];
        }
        $cartList = $goodsInfo;
        $shop_id = $entrustInfo -> shop_id;
        //次日达普通商品
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        $res = $this->checkCrdCartGoods($shop_id, $cartList,$redis);
        $generalCartList = $res['cartList'];
        $generalSellOutGoodsTitle = $res['sellOutGoodsTitle'];
        //次日达秒杀商品
        $seckill = $this->checkCrdCartGoodsSeckill($shop_id, $cartList, $mid,$redis);
        $seckillCartList = $seckill['cartList'];
        $seckillSellOutGoodsTitle = $seckill['sellOutGoodsTitle'];
        $cartList = array_merge($generalCartList, $seckillCartList);
        $goodsTotalMoney = $goodMarketTotalMoney = $goodsNum = $discountClassPrice = 0;
        foreach ($cartList as $k => $v) {
            $cartList[$k]['price_selling'] = $cartList[$k]['dis_unit_price'];
            $goodMarketTotalMoney += bcmul((string) $cartList[$k]['goods_num'], (string) ($cartList[$k]['price_market'] * 100), 2); // 市场价
            $goodsTotalMoney += bcmul((string)$cartList[$k]['subtotal'], '100', 2); // 商品未优惠合计（分）
            $discountClassPrice += bcsub((string)$cartList[$k]['subtotal'] * 100, (string)$cartList[$k]['dis_subtotal'] * 100, 2); // 商品优惠（分）
            $goodsNum += $cartList[$k]['goods_num'];
        }
        $goodsDiscountPrice = bcdiv((string)bcsub((string)$goodsTotalMoney, (string)$discountClassPrice, 2), '100', 2);   // 商品优惠后金额（元）
        $sellOutGoodsTitle = array_merge($seckillSellOutGoodsTitle, $generalSellOutGoodsTitle);
        if (empty($cartList) && empty($sellOutGoodsTitle)) {
            return $this->error(ErrorCode::CART_NULL);
        }
        // 拼团人数团信息
        $activity_type = 0;
        $groupNum = 0;
        $shopInfo = $this->confirmOrderShopInfo($param);
        $goods_pick_time = $generalCartList ? max(array_column($generalCartList, 'goods_pick_time')) : '';
        $peckTime = $this->timePeriodSettings($shopInfo, (string) $goods_pick_time);
        $data = [
            'activity_type' => $activity_type,
            'groupNum' => $groupNum,
            'shop_info' => $shopInfo,
            'goods_list' => $cartList,
            'goods_num' => $goodsNum,
            'TotalMoney' => $goodsDiscountPrice, //代客下单优惠后商品总价
            'peckTime' => $peckTime,
            'discountMoney' => bcdiv(bcsub((string) $goodMarketTotalMoney, (string) $goodsTotalMoney, 2), '100', 2),
            'sellOutGoodsTitle' => $sellOutGoodsTitle,
            'amount' => bcdiv((string)$goodsTotalMoney, '100', 2), // 商品未优惠总金额
            'dis_amount' => $goodsDiscountPrice,
            'discount' => $entrustInfo -> discount,
            'share' => $entrustInfo -> share,
            'status' => $entrustInfo -> status,
        ];
        return $this->success($data);
    }
    /**
     * 待废弃
     * 次日达 获取确认订单数据
     * @param array $param
     * @return array
     * @author lulongfei
     */
    public function getConfirmOrderInfoTomorrow(array $param)
    {
        $shop_id = (int)$param['shop_id'];
        $mid = (int)$param['mid'];
        $cart = $this->cartService->checkCart($mid,$shop_id,self::CART_SOURCE_2);
        if ($cart['code']) {
            return $this->error($cart['code']);
        }
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        $cartList = $cart['cartList'];
        //次日达普通商品
        $res = $this->checkCrdCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];
        $generalSellOutGoodsTitle = $res['sellOutGoodsTitle'];
        //次日达秒杀商品
        $seckill = $this->checkCrdCartGoodsSeckill($shop_id,$cartList,$mid,$redis);
        $seckillCartList = $seckill['cartList'];
        $seckillSellOutGoodsTitle = $seckill['sellOutGoodsTitle'];
        $cartList = array_merge($generalCartList,$seckillCartList);
        $goodsTotalMoney = $goodMarketTotalMoney = $goodsNum = 0;
        foreach ($cartList as $k => $v) {
            $goodMarketTotalMoney += bcmul((string)$cartList[$k]['goods_num'], (string)($cartList[$k]['price_market'] * 100), 2);
            $goodsTotalMoney += bcmul((string)$cartList[$k]['goods_num'], (string)($cartList[$k]['price_selling'] * 100), 2);
            $goodsNum += $cartList[$k]['goods_num'];
        }
        $sellOutGoodsTitle = array_merge($seckillSellOutGoodsTitle,$generalSellOutGoodsTitle);
        if(empty($cartList)&&empty($sellOutGoodsTitle)){
            return $this->error(ErrorCode::CART_NULL);
        }
        // 拼团人数团信息
        $activity_type = 0;
        $groupNum = 0;
        $shopInfo = $this->confirmOrderShopInfo($param);
        $goods_pick_time = $generalCartList?max(array_column($generalCartList, 'goods_pick_time')):'';
        $peckTime = $this->timePeriodSettings($shopInfo, (string)$goods_pick_time);
        $data = [
            'activity_type' => $activity_type,
            'groupNum' => $groupNum,
            'shop_info' => $shopInfo,
            'goods_list' =>$cartList,
            'goods_num' => $goodsNum,
            'TotalMoney' => bcdiv((string)$goodsTotalMoney, '100', 2),
            'peckTime' => $peckTime,
            'discountMoney' => bcdiv(bcsub((string)$goodMarketTotalMoney, (string)$goodsTotalMoney, 2), '100', 2),
            'sellOutGoodsTitle' => $sellOutGoodsTitle
        ];
        return $this->success($data);
    }

    /**
     * 平台次日达商城订单服务
     * @param int $mid
     * @param array $params
     * @return array
     * @author ran
     * @date 2021-04-16 10:18
     * mailbox 466180170@qq.com
     */
    public function createOverNightShopOrderInfo(int $mid,array $params){
          $insideCallParams=$insideOrder=[];
          $userInfo = $this->memberService->findFirst(['mid' => $mid],['mid', 'openid', 'phone'])->toArray();
          $needExceptKey=['status','goods_pick_time'];
          $needActivityExceptKey=['activity_shop_ids','per_can_buy_num','activity_price_market','activity_price_selling','activity_status','begin_date','end_date'];
          $orderGoodsCollection =$this->getCommonOverNightConfirmOrderGoodsCollection((int)$params['shop_id'],$mid,$needExceptKey,$needActivityExceptKey);
          $orderGoodsList=$orderGoodsCollection['orderGoodsList'];
          $orderInfoCollection =$this->getCommonShopCouponOrderCollectionByCartGoods($cartGoodsList);
          $appointment_date =self::getPickOrderAppointmentDate((string)$params['appointment_time']);
          $insideOrder=['deal_type'=>self::ORDER_DEAL_TYPE_2,'order_source'=>self::ORDER_SOURCE_1,'order_type_status'=>self::ORDER_TYPE_STATUS_2];
          $insideCallParams=['appointment_date'=>$appointment_date];
          return $this->createCommonShopOrderInfo($userInfo,$orderInfoCollection,$orderGoodsList,$params,$insideOrder,$insideCallParams);
    }
    /**
     * 平台次日达获取订单信息服务
     * @param int $shop_id
     * @param int $mid
     * @return array
     * @author ran
     * @date 2021-04-05 11:17
     * mailbox 466180170@qq.com
     */
    public function getOverNightShopConfirmOrderInfo(array $params,int $mid)
    {
          $shopInfo = $this->shopService->getInfoByShopId((int)$shop_id, ['shop_id', 'shop_name', 'address', 'shop_tel', 'shop_desc', 'end_time', 'start_time','longitude','latitude']);
          $needExceptKey=['crd_cate_id','subtotal','cate_id','cart_id','activity_goods_id','status','number_stock','goods_pick_time','cart_id','wx_crm_code','kz_goods_id','kz_type_id','lsy_goods_name','lsy_unit_name','lsy_class_name','ratio','scant_id','commission','limite_num_per_day','entrust_order_id'];
          $needActivityExceptKey=['activity_shop_ids','per_can_buy_num','activity_goods_id','activity_price_market','activity_price_selling','activity_status','number_stock','begin_date','end_date'];
          $orderGoodsCollection=$this->getCommonOverNightConfirmOrderGoodsCollection((int)$params['shop_id'],(int)$params['platform_type'],$mid,$needExceptKey,$needActivityExceptKey,$shopInfo,(int)$params['entrust_order_id']);
          $orderResource =$this->getCommonShopConfirmOrderCollectionByGoods((int)$params['shop_id'],(int)$params['platform_type'],$orderGoodsCollection['orderGoodsList'],$shopInfo);
          return $this->success($orderResource);
    }

    /**
     * 待废弃
     * 立即购买获取数据
     * @param array $param
     * @return array
     * @author lulongfei
     */
    public function getActivityConfirmInfo(array $param)
    {
        $shop_id = $param['shop_id'];
        $goodsByActivity = $this->activityService->getActivityGoodsInfo((int)$param['activityID'], (int)$shop_id);
        if (empty($goodsByActivity)) {
            return $this->error(ErrorCode::GOODS_INVALID);
        }
        $order_info = [];
        if ($param['order_no']) {
            $order_info = $this->orderRepository->getOrderInfo($param['order_no']);
        }
        if (empty($order_info)) {
            $order_info = ['num' => 0, 'goods_price' => 0, 'total_price' => 0];
        }
        $shopInfo = $this->confirmOrderShopInfo($param);
        $data = [
            'shop_info' => $shopInfo,
            'order_info' => $order_info,
            'goodsByActivity' => $goodsByActivity,
            'peckTime'=>self::getTimeForGroupBuy(json_decode($goodsByActivity['activity_prams'], true))
        ];
        return $this->success($data);
    }

    /**
     * 待废弃
     * 立即购买确认订单
     * @param array $param
     * @return array
     * @author lulongfei
     */
    public function activityConfirmOrder(array $param)
    {
        if(!$this->shopService->getShopInfobyShopIds([$param['shop_id']],['shop_id'])->toArray()){
            return $this->error(ErrorCode::SHOP_STATUS_CLOSE);
        }
        $res = $this->saveActivityOrder($param);
        return  $res;
    }

    /**
     * 平台免单活动确认订单信息服务
     * @param int $shop_id
     * @param int $activity_goods_id
     * @param string $order_no
     * @return array
     * @author ran
     * @date 2021-03-24 13:52
     * mailbox 466180170@qq.com
     */
    public function getFreeActivityConfirmInfo(int $shop_id,int $activity_goods_id){
        $shopInfo = $this->shopService->getInfoByShopId((int)$shop_id, ['shop_id', 'shop_name', 'address', 'shop_tel', 'shop_desc', 'end_time', 'start_time','longitude','latitude']);
        $exceptKey=['ratio','scant_id','crd_cate_id','lsy_goods_name','lsy_class_name','crd_cate_id','kz_goods_id','wx_crm_code','cate_id','need_invited_num','commission','lsy_unit_name','kz_type_id'];
        $activityGoodsInfo =$this->freeMiniService->getFreeActivityGoodsfirstById($activity_goods_id,$exceptKey);
        $pickTime = $this->timePeriodSettings($shopInfo, (string)$activityGoodsInfo['goods_pick_time']);
        $activityGoodsInfo['goods_pick_time_view'] =$this->getOverNightTakeDate().' '.substr($activityGoodsInfo['goods_pick_time'], 0, 5);
        $goodsNumber =1;
        $data = ['shopInfo' => $shopInfo, 'pickTime'=>$pickTime, 'activityGoodsInfo' => $activityGoodsInfo, 'orderInfo' => ['goodsNumber'=>$goodsNumber, 'orderTotalMoney'=>bcmul($activityGoodsInfo['activity_price_selling'],100)], 'orderInfoCallBack' => []];
        return $this->success($data);
    }

    /**
     * 平台免单活动创建订单信息服务
     * @author ran
     * @date 2021-03-25 11:41
     * mailbox 466180170@qq.com
     */
    public function createFreeActivityOrderInfo(int $mid,array $params){
        $userInfo = $this->memberService->findFirst(['mid' => $mid],['mid', 'openid', 'phone'])->toArray();
        $insideOrder=['activity_type'=>self::ACTIVITY_TYPE_1,'order_type'=>self::ORDER_TYPE_10,'platform_type'=>self::PLATFORM_TYPE_1];
        $insideCallParams=['free_num'=>self::FREE_NUM_1,'free_step'=>self::FREE_STEP_1];
        $activityGoodsInfo =$this->freeMiniService->getFreeActivityGoodsfirstById($params['activity_goods_id']);
        $activityInfo =$this->freeMiniService->getFreeActivityInfofirstById($params['activity_goods_id']);
        return $this->createCommonActivityOrderInfo($userInfo,$insideOrder,$activityGoodsInfo,$activityInfo,$params,$insideCallParams);
    }

    /**
     * 校验及时达限购
     * @param int $shop_id
     * @param array $cartList
     * @param int $mid
     * @return array|array[]
     * @author lulongfei
     */
    public function checkCartGoodsQuota(int $shop_id,array $cartList, int $mid,object $redis)
    {
        //区分普通商品 和限购商品
        foreach ($cartList as $k=> $item){
            if($item['group_id']!=Stakeholder::GROUP_ID_3){
                unset($cartList[$k]);
            }
        }
        if(empty($cartList)){
            return ["cartList"=>[],"sellOutGoods"=>[],"sellOutGoodsTitle"=>[]];
        }
        $goodsInfo = $this->activityService::getQuotaGoodsList(array_column($cartList, 'activity_goods_id'),$shop_id);
        $goodsIdsArr = array_column($goodsInfo, null,'goods_id');

        $sellOutGoods = [];
        $sellOutGoodsTitle = [];
        $_buy_num_arr = $this->orderRepository->getSeckillOrderNum(array_column($cartList,'activity_goods_id'),$mid);
        $buyNumById = array_column($_buy_num_arr,'num','activity_goods_id');
        foreach ($cartList as $k=> $v) {
            if(!isset($goodsIdsArr[$cartList[$k]['goods_id']])){
                //没有参与活动或下架  删除商品
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                unset($cartList[$k]);
                continue;
            }
            $cartList[$k] = array_merge($cartList[$k],$goodsIdsArr[$cartList[$k]['goods_id']]);
            $buy_num = $buyNumById[$cartList[$k]['activity_goods_id']]??0;
            $quotaNum = json_decode($cartList[$k]['activity_prams'],true);
            if($cartList[$k]['stock']==0||$quotaNum['stock'] < $cartList[$k]['goods_num']||$quotaNum<=$buy_num){
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                unset($cartList[$k]);
                continue;
            }
            $cartList[$k]['kz_self_num'] = $this->getKzSelfNum($cartList[$k]['goods_id'],$redis,2);
        }
        sort($cartList);
        return compact("cartList","sellOutGoods","sellOutGoodsTitle");
    }
    /**
     * 校验普通及时达
     * @param int $shop_id
     * @param array $cartList
     * @return array|array[]
     * @author lulongfei
     */
    public function checkCartGoods(int $shop_id,array $cartList,object $redis)
    {

        //区分普通次日达商品 和秒杀商品
        foreach ($cartList as $k=> $item){
            if($item['group_id']==Stakeholder::GROUP_ID_3){
                unset($cartList[$k]);
            }
        }
        if(empty($cartList)){
            return ["cartList"=>[],"sellOutGoods"=>[],"sellOutGoodsTitle"=>[]];
        }
        $_goodsIds = array_column($cartList, 'goods_id');
        $goodsIds = $this->goodsService->getGoodsIds($_goodsIds,$shop_id);
        $goodsInfo = $this->goodsService::getGoodsInfoData($shop_id, $goodsIds, $this->goodsService::STOCK_TYPE_0);
        $goodsIdsArr = array_column($goodsInfo, null,'goods_id');
        $sellOutGoods = [];
        $sellOutGoodsTitle = [];
        foreach ($cartList as $k =>$v) {
            if(!isset($goodsIdsArr[$cartList[$k]['goods_id']])){
                //下架  删除商品
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                unset($cartList[$k]);
                continue;
            }
            $cartList[$k] = array_merge($cartList[$k],$goodsIdsArr[$cartList[$k]['goods_id']]);
            if ($cartList[$k]['scant_id'] == $this->goodsService::GOODS_SCANT_1) {
                $stock = $cartList[$k]['ratio'] ? bcdiv((string)$cartList[$k]['surplusQuantity'], (string)$cartList[$k]['ratio']) : (string)$cartList[$k]['surplusQuantity'];
            } else {
                $stock = bcdiv((string)$cartList[$k]['surplusQuantity'], '1000');
            }
            if (!$this->cartService->checkStock((int)$stock, $cartList[$k]['goods_num'], $shop_id, $cartList[$k]['goods_id'], $cartList[$k]['scant_id'], $cartList[$k]['ratio'])) {
                //没有库存
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                unset($cartList[$k]);
                continue;

            }

            $cartList[$k]['kz_self_num'] = $this->getKzSelfNum((int)$cartList[$k]['goods_id'],$redis);
        }
        sort($cartList);
        return compact("cartList","sellOutGoods","sellOutGoodsTitle");
    }

    /**
     * 获取货架号（及时达）
     * type 0 普通品 1 秒杀 2限购
     * @param int $goods_id
     * @param object $redis
     * @return string
     */
    public function getKzSelfNum(int $goods_id,object $redis,int $type=0)
    {
        $key = $type==1? (string)$goods_id.'ms':( $type==2?(string)$goods_id.'xg':(string)$goods_id);
        if(!$kz_self_num = $redis->hGet('goodsShelve:kzSelfNum', $key)){
            $kz_self_num = 'xp'.Random::character(8);
            $redis->hSet('goodsShelve:kzSelfNum', $key, $kz_self_num);
        }
        return $kz_self_num;
    }

    /**
     * 校验次日达秒杀商品
     * @param int $shop_id
     * @param array $cartList
     * @param int $mid
     * @return array
     * @author lulongfei
     */
    public function checkCrdCartGoodsSeckill(int $shop_id,array $cartList, int $mid,object $redis)
    {
        //区分普通次日达商品 和秒杀商品
        foreach ($cartList as $k=> $item){
            if($item['group_id']!=Stakeholder::GROUP_ID_4){
                unset($cartList[$k]);
            }
        }
        if(empty($cartList)){
            return ["cartList"=>[],"sellOutGoods"=>[],"sellOutGoodsTitle"=>[]];
        }
        $goodsInfo = $this->activityService::getSeckillGoodsList(array_column($cartList, 'activity_goods_id'),$shop_id);
        $goodsIdsArr = array_column($goodsInfo, null,'goods_id');

        $sellOutGoods = [];
        $sellOutGoodsTitle = [];
        $data = [];
        $_buy_num_arr = $this->orderRepository->getSeckillOrderNum(array_column($cartList,'activity_goods_id'),$mid);
        $buyNumById = array_column($_buy_num_arr,'num','activity_goods_id');
        foreach ($cartList as $k=> $v) {
            if(!isset($goodsIdsArr[$cartList[$k]['goods_id']])){
                //没有参与活动或下架  删除商品
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                continue;
            }
            $cartList[$k] = array_merge($cartList[$k],$goodsIdsArr[$cartList[$k]['goods_id']]);
            if($cartList[$k]['stock']==0||$cartList[$k]['stock'] < $cartList[$k]['goods_num']){
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                continue;
            }
            $buy_num = $buyNumById[$cartList[$k]['activity_goods_id']]??0;
            if($cartList[$k]['per_can_buy_num'] <= $buy_num){
                $cartList[$k]['price_selling'] =  $cartList[$k]['price_market'];
                $cartList[$k]['kz_self_num'] = $this->getKzSelfNum($cartList[$k]['goods_id'], $redis);
                $data[] = $cartList[$k];

            }else{
                $num = $cartList[$k]['per_can_buy_num'] - $buy_num;//除去购买剩余限购数量
                $goodsNum = $cartList[$k]['goods_num'];
                if($num >= $goodsNum){//购买数量未超过限购数量情况
                    $cartList[$k]['kz_self_num'] = $this->getKzSelfNum($cartList[$k]['goods_id'], $redis,1);
                    $data[] = $cartList[$k];

                }else{
                    //分离超出限购数量的商品  原价购买
                    // 秒杀价
                    $cartList[$k]['goods_num'] = $num;
                    $cartList[$k]['kz_self_num'] = $this->getKzSelfNum($cartList[$k]['goods_id'], $redis,1);
                    $data[] =  $cartList[$k];
                    //原价
                    $number = $goodsNum - $num;
                    $cartList[$k]['price_selling'] =  $cartList[$k]['price_market'];
                    $cartList[$k]['goods_num'] = $number;
                    $cartList[$k]['group_id'] =0;
                    $cartList[$k]['kz_self_num'] = $this->getKzSelfNum($cartList[$k]['goods_id'], $redis);
                    $data[] = $cartList[$k];
                }

            }
        }
        $cartList = $data;
        return compact("cartList","sellOutGoods","sellOutGoodsTitle");

    }
    /**
     * 校验次日达购物车普通商品
     * @param array $param
     * @param array $cartList
     * @return array
     * @author lulongfei
     */
    public function checkCrdCartGoods(int $shop_id,array $cartList,object $redis)
    {
        //区分普通次日达商品 和秒杀商品
        foreach ($cartList as $k=> $item){
            if($item['group_id']==Stakeholder::GROUP_ID_4){
                unset($cartList[$k]);
            }
        }
        if(empty($cartList)){
            return ["cartList"=>[],"sellOutGoods"=>[],"sellOutGoodsTitle"=>[]];
        }
        $_goodsIds = array_column($cartList, 'goods_id');
        $goodsIds = $this->goodsService->getGoodsIds($_goodsIds,$shop_id,2);
        $goodsInfo = $this->goodsService::getCrdGoodsInfoData($goodsIds);
        $goodsIdsArr = array_column($goodsInfo, null,'goods_id');
        $sellOutGoods = [];
        $sellOutGoodsTitle = [];
        foreach ($cartList as $k =>$v) {
            if(!isset($goodsIdsArr[$cartList[$k]['goods_id']])){
                //下架  删除商品
                $sellOutGoods[] = $cartList[$k]['goods_id'];
//                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                unset($cartList[$k]);
                continue;
            }
            $cartList[$k] = array_merge($cartList[$k],$goodsIdsArr[$cartList[$k]['goods_id']]);
            $stock = $cartList[$k]['number_stock'];
            if (!$this->cartService->checkStock((int)$stock, $cartList[$k]['goods_num'], $shop_id, $cartList[$k]['goods_id'], $cartList[$k]['scant_id'], $cartList[$k]['ratio'])) {
                //没有库存
                $sellOutGoods[] = $cartList[$k]['goods_id'];
                $sellOutGoodsTitle[] = $cartList[$k]['title'];
                unset($cartList[$k]);
                continue;

            }
            $cartList[$k]['kz_self_num'] = $this->getKzSelfNum($cartList[$k]['goods_id'], $redis);
        }
        sort($cartList);
        return compact("cartList","sellOutGoods","sellOutGoodsTitle");
    }
    /**
     * 次日达商品每人每天已经购买的数量
     * @param array $where
     * @param array|null $in
     * @return array
     */
    public function nextDayGoodsNumOfMid(array $where, ?array $in = null){
        $field = [
            'sum(og.number) as num',
            'og.goods_id',
        ];
        return OrderModel::query()
            ->from('store_order as order')
            ->rightJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->selectRaw(implode(',', $field))
            ->where($where)
            ->where('order.order_source', Stakeholder::NEXT_DAY_ORDER)
            ->where('order.is_pay', Stakeholder::ORDER_PAID)
            ->whereBetween('order.pay_at', [date('Y-m-d'), date('Y-m-d 23:59:59')])
            ->when($in, function ($query, $in) {
                foreach ($in as $k => $v) {
                    $query->whereIn($v[0], $v[1]);
                }
                return $query;
            })
            ->groupBy(['goods_id'])
            ->get()->toArray();
    }
    /**
     * 根据付款时间区间获取下单手机号
     * @param array $dateArr
     * @return array
     */
    public function getOrderPhoneByDateRange(array $dateArr = [])
    {
        if (!empty($dateArr)) {
            return OrderModel::query()
                ->whereBetween('pay_at', [$dateArr['start'], $dateArr['end']])
                ->pluck('order_phone')
                ->toArray();
        }
        return [];

    }
    /**
     * 确认订单获取店铺或团长信息
     * @param array $param
     * @return array|mixed
     * @author lulongfei
     */
    public function confirmOrderShopInfo(array $param)
    {
        if(!isset($param['leader_id'])||empty($param['leader_id'])){
            $shopInfo = $this->shopService->getInfoByShopId((int)$param['shop_id'], ['shop_id', 'shop_name', 'address', 'shop_tel', 'shop_desc', 'end_time', 'start_time','longitude','latitude']);
            $shopInfo['tag'] =Stakeholder::TAG_1;
            $shopInfo['leader_id'] ='';
        }else {
            $_shopInfo = TeamLeaderService::getTeamLeaderInfo((int)$param['leader_id'], ['id', 'shop_id', 'name', 'delivery_address', 'detail_address', 'phone', 'closing_time', 'opening_time', 'longitude', 'latitude']);
            $shopInfo = [
                'shop_id' => $_shopInfo['shop_id'],
                'leader_id' => $_shopInfo['id'],
                'shop_name' => $_shopInfo['name'],
                'shop_tel' => $_shopInfo['phone'],
                'address' => $_shopInfo['delivery_address'] . $_shopInfo['detail_address'],
                'end_time' => $_shopInfo['closing_time'],
                'start_time' => $_shopInfo['opening_time'],
                'longitude' => $_shopInfo['longitude'],
                'latitude' => $_shopInfo['latitude'],
                'tag' => Stakeholder::TAG_2
            ];
        }
        return $shopInfo;
    }
    /**
     * 次日达意向提货时间
     * @param array $shopInfo
     * @param string $goods_pick_time
     * @return array
     * @author lulongfei
     */
    public function timePeriodSettings(array $shopInfo, string $goods_pick_time)
    {
        $currentTime = date('H:i:s');
        $cut_off_time = $this->systemService->getSystemInfo(['name' => 'cut_off_time']);
        $_pick_date_config =  $this->systemService->getSystemInfo(['name' => 'pick_date_config']);
        $pick_date_config = explode(',', $_pick_date_config);
        $pick_date_arr = [];
        foreach ($pick_date_config as $v) {
            $timeArr = explode('-', $v);
            if ($timeArr[1] > $goods_pick_time && $timeArr[1] < $shopInfo['end_time']) {
                $pick_date_arr[] = $v;
            }
        }

        $week = self::get_week('+1 days');
        if ($currentTime > $cut_off_time) {
            $week = self::get_week('+2 days');
        }
        return ['week' => [$week], 'pick_date' => $pick_date_arr];
    }
    /**
     * 及时达意向自提时间
     * @return array|string[]
     */
    public  function getTodayPickTime(){
        $_pick_date=$this->systemService->getSystemInfo(['name' => 'pick_date_config']);
        $pick_date = explode(',',$_pick_date);
        $time =date('H:i',time());
        $pick_date_arr=[];
        foreach($pick_date as $v){
            $timeArr =explode('-',$v);
            if($timeArr[1]>$time){
                $pick_date_arr[]=$timeArr[0].'-'.$timeArr[1];
            }
        }
        if(!empty($pick_date_arr)){
            $pick_push =['尽快送达(预计'.date('H:i',strtotime($time)+60*60).')前'];
            $dateArr =array_merge($pick_push,$pick_date_arr);
        }else{
            $dateArr =[];
        }
        return $dateArr;
    }
    /**
     * 及时达意向配送时间
     * @return array|string[]
     */
    public  function getTodayDeliverTime(){
        $_pick_date=$this->systemService->getSystemInfo(['name' => 'match_date_config']);
        $pick_date = explode(',',$_pick_date);
        $time =date('H:i',time());
        $pick_date_arr=[];
        foreach($pick_date as $v){
            $timeArr =explode('-',$v);
            if($timeArr[1]>$time){
                $pick_date_arr[]=$timeArr[0].'-'.$timeArr[1];
            }
        }
        if(!empty($pick_date_arr)){
            $pick_push =['尽快送达(预计'.date('H:i',strtotime($time)+60*60).')前'];
            $dateArr =array_merge($pick_push,$pick_date_arr);
        }else{
            $dateArr =[];
        }
        return $dateArr;
    }
    /**
     * 立即购买意向提货时间
     * @param array $activity_prams
     * @return array
     */
    public static function getTimeForGroupBuy(array $activity_prams){
        // 获取activityID==>activity_prams==>pick_time
        $pick_name = $activity_prams['pick_time'];
        $startTime = substr($pick_name, 0, 10); //2020-06-03
        $endTime = substr($pick_name, -10); // 2020-07-01
        $dateArr=[];
        if(strtotime($startTime) <= time() && time() <= strtotime($endTime.' 23:59:59')){
            $dateArr = (new BaseService())->prDates(date('Y-m-d',time()), $endTime);
        }elseif (strtotime($startTime) >= time()){
            $dateArr =(new BaseService())->prDates($startTime, $endTime);
        }
        $tmp = [];
        $weekArr = ['周日', '周一', '周二', '周三', '周四', '周五', '周六'];
        foreach ($dateArr as $k => $v){
            $tmp[$k]['week'] = $weekArr[date('w', strtotime($v) )] . ' ' . substr($v,5);
            if( date('j' , strtotime($v) ) == date('j',time())){
                $tmp[$k]['time'] = array_column(self::prTimes(date('H:00',time()),'19:00'),'date');
            }else{
                $tmp[$k]['time'] = array_column(self::prTimes('07:00','19:00'),'date');
            }
        }
        $data_Arr =[];
        foreach($tmp as $k=>$value){
            if(!empty($tmp[$k]['time'])){
                $data_Arr[]=$value;
            }
        }
        return $data_Arr;
    }
    /**
     * 分享订单详情
     * @param int $mid
     * @param string $order_no
     * @return array
     */
    public function shareOrderDetail(int $mid, string $order_no)
    {

        return $this->orderRepository->shareOrderDetail($mid,$order_no);

    }
    /**
     * 分享订单商品列表
     * @param int $mid
     * @param string $order_no
     * @return array
     */
    public function shareGoods(int $mid, string $order_no)
    {
        $orderDetail = $this->orderRepository->getShareGoods($order_no);
        //1及时达 2次日达 3拼团 4接龙 5免单
        $orderType = 1;
        switch ($orderDetail['order_type']){
            case self::ORDER_TYPE_0:
            case self::ORDER_TYPE_2:
                $orderType =1;
                break;
            case self::ORDER_TYPE_6:
                $orderType = 3;
                break;
            case self::ORDER_TYPE_8:
            case self::ORDER_TYPE_9:

                $orderType =2;
                break;
            case self::ORDER_TYPE_7:
                $orderType =4;
                break;
            case self::ORDER_TYPE_10:
                $orderType =5;
                break;
            default:
                break;
        }
        $shop_id = $orderDetail['shop_id'];
        //区分订单类型
        $totalMoney = 0;
        $goods_num = 0;
        $discountMoney = 0;
        $goodsList = $orderDetail['goods'];
        //有效
        $effectiveGoodsList = [];
        //无效下架
        $invalidGoodsList = [];
        $peckTime =[];
        if ($orderDetail['order_source'] == self::ORDER_SOURCE_0) {
            //普通商品
            $goodsId = [];
            //限购商品
            $activityGoodsId = [];
            foreach ($goodsList as $v){
                if($v['group_id']==Stakeholder::GROUP_ID_3){
                    $activityGoodsId[] = $v['activity_goods_id'];
                    continue;
                }
                $goodsId[] = $v['goods_id'];
            }
            $quotaGoods = $this->activityService->getActivityGoodsList($activityGoodsId);
            //及时达//有效
            $goodsIdEffective = $this->goodsService->getGoodsIds($goodsId,$shop_id);
            //无效
            $goodsIdInvalid = array_diff($goodsId,$goodsIdEffective);
            //有效商品
            $effectiveGoodsList = $this->goodsService::getGoodsInfoData($shop_id, $goodsIdEffective, $this->goodsService::STOCK_TYPE_0);
            //无效商品
            $invalidGoodsList = $this->goodsService::getGoodsInfoData($shop_id, $goodsIdInvalid, $this->goodsService::STOCK_TYPE_1);
            $date = date('Y-m-d H:i:s');
            foreach ($quotaGoods as $v){
                if($v['stock']<0||$v['status']==0||$v['is_deleted']==1||!in_array($shop_id,explode(',',$v['shop_ids']))||$v['begin_date']>$date||$v['end_date']<$date){
                    $invalidGoodsList[] = $v;
                    continue;
                }
                $effectiveGoodsList[] = $v;
            }
            $cart = $this->cartService->checkCart($mid, $shop_id,self::CART_SOURCE_1);

            $cartList = $cart['cartList'] ?? [];
            $quotaCartList = $generalCartList =[];
            foreach ($cartList as &$v){
                $v['id'] = $v['cart_id'];
                if($v['group_id']==Stakeholder::GROUP_ID_3){
                    $quotaCartList[] = $v;
                    continue;
                }
                $generalCartList[] = $v;
            }
            $generalCartListByGoodsId = array_column($generalCartList, null, 'goods_id');
            $quotaCartListByGoodsId = array_column($quotaCartList, null, 'goods_id');
            foreach ($effectiveGoodsList as $item) {
                if(isset($item['group_id'])&&$item['group_id']==Stakeholder::GROUP_ID_3){
                    $item['goods_num'] = $quotaCartListByGoodsId[$item['goods_id']]['goods_num']??0;
                    continue;
                }
                $item['goods_num'] = $generalCartListByGoodsId[$item['goods_id']]['goods_num']??0;
            }
            foreach ($invalidGoodsList as $item) {
                if(isset($item['group_id'])&&$item['group_id']==Stakeholder::GROUP_ID_3){
                    $item['goods_num'] = $quotaCartListByGoodsId[$item['goods_id']]['goods_num']??0;
                    continue;
                }
                $item['goods_num'] = $generalCartListByGoodsId[$item['goods_id']]['goods_num']??0;
            }
            $cartEffectiveArr = $this->cartService::getCartGoodsAll($cartList, array_column($cartList,'goods_id'), $shop_id,$mid, $this->cartService::GOODS_STATUS_0)['cartList'];
            foreach ($cartEffectiveArr as $v) {
                $goods_num += $v['goods_num'];
                $totalMoney += $v['goods_num'] * $v['price_selling'];
                $discountMoney += $v['goods_num'] * ($v['price_market'] - $v['price_selling']);
            }


            $shopInfo = $this->shopService->getInfoByShopId((int)$shop_id,  ['shop_id', 'shop_name', 'address', 'shop_tel', 'shop_desc', 'end_time', 'start_time','longitude','latitude']);
            $peckTime = [
                'start_time' => $shopInfo['start_time'],
                'end_time' => $shopInfo['end_time'],
            ];
        } else {
            $shopInfo = $this->confirmOrderShopInfo(['leader_id' => $orderDetail['leader_id'], 'shop_id' => $shop_id]);
            //次日达
            switch ($orderDetail['order_type']) {
                case self::ORDER_TYPE_6:
                case self::ORDER_TYPE_7:

                    //拼团
                    //接龙
                    //提货时间

                    $activityID = $this->activityService->getActivityId( $goodsList[0]['activity_goods_id']);
                    $goodsByActivity = $this->activityService->getActivityGoodsInfo((int)$activityID, (int)$shop_id,(int)$orderDetail['order_type']);
                    $peckTime = $goodsByActivity?self::getTimeForGroupBuy(json_decode($goodsByActivity['activity_prams'], true)):[];
                    $effectiveGoodsList[] =$goodsByActivity;
                    break;
                case self::ORDER_TYPE_8 :
                case self::ORDER_TYPE_9:

                    $cart = $this->cartService->checkCart($mid, $shop_id,self::CART_SOURCE_2);

                    $cartList = $cart['cartList'] ?? [];


                    //次日达  秒杀

                    $_crdGoods = [];
                    $_skillGoods = [];
                    foreach ($goodsList as $v) {
                        if ($v['group_id'] == Stakeholder::GROUP_ID_4) {
                            $_skillGoods[] = $v;
                        } else {
                            $_crdGoods[] = $v;
                        }

                    }
                    $crdGoods = $this->goodsService::getCrdGoodsInfoData(array_column($_crdGoods, 'goods_id'));
                    $skillGoods =    $this->activityService->getActivityGoodsList(array_column($_skillGoods, 'activity_goods_id'));
                    //包含失效购物车商品的次日达和秒杀商品
                    $crdGoodsCart = [];
                    $skillGoodsCart = [];
                    foreach ($cartList as $k => $item) {
                        if ($item['group_id'] == Stakeholder::GROUP_ID_4) {
                            $skillGoodsCart[$item['goods_id']] = $item;
                        } else {
                            $crdGoodsCart[$item['goods_id']] = $item;
                        }
                    }
                    foreach ($crdGoods as $good) {

                        $good['goods_num'] = $crdGoodsCart[$good['goods_id']]['goods_num'] ?? 0;
                        if ($good['is_deleted'] == 1 || $good['status'] == 0 || in_array($shop_id, explode(',', $good['shop_ids']))) {

                            $invalidGoodsList[] = $good;
                        } else {

                            $effectiveGoodsList[] = $good;
                        }
                    }
                    $_buy_num_arr = $this->orderRepository->getSeckillOrderNum(array_column($skillGoods,'activity_goods_id'),$mid);
                    $buyNumById = array_column($_buy_num_arr,'num','activity_goods_id');
                    foreach ($skillGoods as $good) {
                        $good['goods_num'] = $skillGoodsCart[$good['goods_id']]['goods_num'] ?? 0;
                        $good['goods_pick_time'] = '';
                        $buy_num = $buyNumById[$good['activity_goods_id']]??0;
                        $good['buy_num'] = $buy_num;
                        if ($good['limite_num_per_day'] <= $buy_num) {
                            $good['limite_num'] = 0;
                            //                return ['code'=>ErrorCode::GOODS_INVALID,'msg'=>'商品：'.$cartList[$k]['title'].' 超出秒杀商品限购数量'];
                        } else {
                            $good['limite_num'] = $good['limite_num_per_day'] - $buy_num;
                        }
                        $good['number_stock'] = $good['stock'];
                        if ($good['is_deleted'] == 1 || ($good['status'] != 2 && empty($good['number_stock'])) || !in_array($shop_id, explode(',', $good['shop_ids']))) {
                            $invalidGoodsList[] = $good;
                        } else {
                            $effectiveGoodsList[] = $good;
                        }
                    }
                    $goods_pick_time = $effectiveGoodsList ? max(array_column($effectiveGoodsList, 'goods_pick_time')) : '';
                    $peckTime = self::timePeriodSettings($shopInfo, (string)$goods_pick_time);
                    foreach ($effectiveGoodsList as $k => $v) {
                        $goods_num += $v['goods_num'];
                        if ($v['group_id'] == Stakeholder::GROUP_ID_4) {
                            $totalMoney += ($v['goods_num']>$v['limite_num']?$v['price_market'] * ($v['goods_num'] - $v['limite_num']) + $v['limite_num'] * $v['price_selling']:$v['goods_num']*$v['price_selling'])*100;
                        } else {
                            $totalMoney += $v['goods_num'] * $v['price_selling']*100;
                        }
                        $discountMoney += $v['goods_num'] * ($v['price_market'] - $v['price_selling'])*100;
                        $effectiveGoodsList[$k]['goods_pick_time'] = $this->goodsService->getTakeDate().' '.substr($effectiveGoodsList[$k]['goods_pick_time'],0,5);
                    }

                    break;
                case self::ORDER_TYPE_10:
                    $res =$this->getFreeActivityConfirmInfo((int)$shop_id,$goodsList[0]['activity_goods_id']);
                    if(!$res['code']){
                        $activityInfo = $res['data'];
                        $peckTime  = $activityInfo['pickTime'];
                        $effectiveGoodsList[] = $activityInfo['activityGoodsInfo'];
                    }
                    break;
                default:
                    break;
            }

        }
        //订单类型 提货时间  有效商品  失效商品  店铺信息  订单金额  优惠金额 商品数量
        return compact('orderType','peckTime', 'effectiveGoodsList', 'invalidGoodsList', 'shopInfo', 'totalMoney', 'discountMoney', 'goods_num');
    }
    /**
     * 年度账单  弃用
     * @param int $mid
     * @return array
     */
    public function userOrderBill(int $mid)
    {
        $year = '2020';
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        if($_data = $redis->hget('order:billByMid',(string)$mid)){
            $data = json_decode($_data, true);
            return $data;
        }
        //用户总金额
        $orderMoney = OrderModel::where(['mid' => $mid, 'is_pay' => 1])->whereRaw("create_at > '$year'")->sum('total_price') ?? '';

        if ($_count = $redis->get('order:countByMidAll')) {
            $count = json_decode($_count, true);
        } else {
            //正常情况不走此处
            $count = [];
            $i=0;
            while (true){
                $_count = OrderModel::where(['is_pay' => 1])
                    ->selectRaw('count(*) as num,mid')
                    ->whereRaw("create_at > '$year'")->groupBy(['mid'])->offset($i)->limit(1000)->orderBy('num', 'asc')->get()->toArray();
                if ($_count) {
                    $count =  array_merge($count, $_count);
                }else{
                    break;
                }
                $i +=1000;
            }
            if ($count) {
                $redis->set('order:countByMidAll', json_encode($count));
            }
        }
        //下单用户总人数
        $orderCount = count($count)*30;
        //根据下单数量排序位置
        $midKey = 0;
        //用户下单次数
        $buyCount = 0;
        foreach ($count as $k => $v) {
            if ($v['mid'] == $mid) {
                $midKey = $k + 1;
                $buyCount = $v['num'];
            }
        }
        //用户买单超越百分比
        $midCountPercent ='';
        if($midKey){
            $percent = bcmul(bcdiv((string)$midKey, (string)$orderCount, 5), '100', 2);
            $percent = $percent>=0.01?$percent:0.01;
            $midCountPercent = $percent.'%';
        }

        //注册时间
        $_userRegisterTime = MemberModel::where(['mid' => $mid])->selectRaw(" DATE_FORMAT(register_date,'%Y-%m-%d') as register_date")->first();
        $userRegisterTime = $_userRegisterTime ? $_userRegisterTime['register_date'] : '';
        //注册天数
        $userRegisterDays = $userRegisterTime ? (strtotime(date('Y-m-d')) - strtotime($userRegisterTime)) / 86400 : '';

        //第一次下单时间
        $_userOrderTimeFirst = OrderModel::where(['is_pay' => 1, 'mid' => $mid])->orderBy('create_at', 'asc')->selectRaw(" DATE_FORMAT(create_at,'%Y-%m-%d') as create_at")->first();
        $userOrderTimeFirst = $_userOrderTimeFirst ? $_userOrderTimeFirst['create_at'] : '';
        //分类
        $cateId = OrderGoodsModel::where(['is_pay' => 1, 'mid' => $mid])->whereRaw("create_at > '$year'")->whereRaw('cate_id > 0')->groupBy(['cate_id'])->limit(1)->value('cate_id');//默认倒序
        $cateName = CategoryModel::where(['id' => $cateId])->value('title') ?? '';
        //下单时间段

        $_orderByHour = OrderModel::where(['is_pay' => 1, 'mid' => $mid])
            ->selectRaw("count(*) as num,DATE_FORMAT(create_at,'%H') as hour")
            ->whereRaw("create_at > '$year'")->groupBy(['hour'])->orderBy('hour', 'asc')->get()->toArray();
        $likeBuyTime = '';
        if ($_orderByHour) {
            $orderByHour = array_column($_orderByHour, 'num', 'hour');
            $hour = ['00', '01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23'];
            foreach ($hour as $v) {
                if (!isset($orderByHour[$v])) {
                    $orderByHour[$v] = 0;
                }
            }
            ksort($orderByHour);
            //分割数组
            $orderByHourChunk = array_chunk($orderByHour, 3);
            $max = array_sum($orderByHourChunk[0]);
            $key = 0;
            foreach ($orderByHourChunk as $k => $v) {
                $currentSum = array_sum($v);
                if ($currentSum > $max) {
                    $max = $currentSum;
                    $key = $k;
                }

            }

            switch ($key) {
                case 0:
                    $likeBuyTime = '00:00-03:00';
                    break;
                case 1:
                    $likeBuyTime = '03:00-06:00';
                    break;
                case 2:
                    $likeBuyTime = '06:00-09:00';
                    break;
                case 3:
                    $likeBuyTime = '09:00-12:00';
                    break;
                case 4:
                    $likeBuyTime = '12:00-15:00';
                    break;
                case 5:
                    $likeBuyTime = '15:00-18:00';
                    break;
                case 6:
                    $likeBuyTime = '18:00-21:00';
                    break;
                case 7:
                    $likeBuyTime = '21:00-24:00';
                    break;
                default:
                    break;
            }
        }
        //买菜最多的一天
        $_maxBuyDayArr = OrderGoodsModel::where(['is_pay' => 1, 'mid' => $mid])->whereRaw("create_at > '$year'")->selectRaw("DATE_FORMAT(create_at,'%Y-%m-%d') as time,sum(number) as num")->groupBy(['time'])->get()->toArray();
        //日期
        $maxBuyDay = '';
        if ($_maxBuyDayArr) {
            $maxBuyDayArr = $_maxBuyDayArr[0];
            foreach ($_maxBuyDayArr as $k => $v) {
                if ($v['num'] > $maxBuyDayArr['num']) {
                    $maxBuyDayArr = $v;
                }
            }

            $maxBuyDay = $maxBuyDayArr['time'];
        }
        //用户当年消费总金额 下单买菜次数 用户买单超越百分比 注册时间 注册天数 第一次下单时间 最喜欢买的商品分类 最喜欢买的时间段 买菜最多的一天
        $data = compact('orderMoney', 'buyCount','midCountPercent', 'userRegisterTime', 'userRegisterDays', 'userOrderTimeFirst', 'cateName', 'likeBuyTime', 'maxBuyDay');
        $redis->hSet('order:billByMid', (string)$mid,json_encode($data));
        return $data;
    }

    /**
     * 团长订单列表
     * @param array $field
     * @param array $param
     * @param int $id
     * @param int $perPage
     * @return \Hyperf\Contract\LengthAwarePaginatorInterface
     */
    public function teamOrder(array $field, array $param, int $id, int $perPage)
    {
        $where = [
            'is_pay' => 1,
            'is_deleted' => 0,
            'leader_id' => $id,
            'deal_type' => 2,
            'order_type_status' => 2
        ];
        $whereIn = [];
        switch ($param['order_status']) {
            case 1:
                $whereIn = [3, 4, 5];
                break;
            case 2:
                $whereIn = [3];
                break;
            case 3:
                $whereIn = [4];
                break;
            case 4:
                $whereIn = [5];
                break;
            default:
                break;
        }
        return  $this->orderRepository->getTeamLeaderOrderList($where,$whereIn,$field,$perPage);
    }

    /**
     * 团长订单详情
     * @param string $order_no
     * @param int $id
     * @return mixed
     */
    public function teamOrderDetail(string $order_no, int $id)
    {
        $where = [
            'is_pay' => 1,
            'is_deleted' => 0,
            'leader_id' => $id,
            'order_no' => $order_no,
            'deal_type' => 2,
            'order_type_status' => 2
        ];
        $orderField = [
            'order_no',
            'create_at',
            'order_commission',
            'total_price',
            'goods_price',
            'status',
            'appointment_time',
            'write_off_code',
            'order_phone',
            'mid',
            'shop_id',
            'leader_id',
            'address_id',
            'pay_type'
        ];
        $orderGoodsField = [
            'goods_title',
            'goods_spec',
            'goods_logo',
            'selling_price',
            'market_price',
            'number',
            'order_no',
            'take_num',
            'id as order_goods_id'
        ];
        $orderDetail = $this->orderRepository->teamOrderDetail($where,$orderField,$orderGoodsField);
        $orderDetail['discountMoney'] = 0;
        $orderDetail['order_refund_price'] = 0;
        if ($orderDetail['status'] == 5) {
            if ($orderDetail['pay_type'] == 1) {
                //微信  统计吾响退款log
                $orderDetail['order_refund_price'] = WxRefundLogModel::where(['order_no' => $orderDetail['order_no']])->sum('refund_total_money');
            } else {
                //余额 统计客至退款log
                $orderDetail['order_refund_price'] = KzRefundLogModel::where(['order_no' => $orderDetail['order_no']])->sum('refund_total_money');
            }
        }
        foreach ($orderDetail->goods as $k => $v) {
            $orderDetail['discountMoney'] = bcadd((string)$orderDetail['discountMoney'], ($v->market_price ? bcmul((string)bcsub((string)$v->market_price, (string)$v->selling_price, 2), (string)$v->number, 2) : 0), 2);
        }
        return $orderDetail;
    }

    /**
     * 获取接龙活动下单用户id
     * @param array $where
     * @return array
     */
    public function getFollowGoodsInfo(array $where)
    {
        $orderUser = OrderGoodsModel::query()
            ->join('store_order as o', 'o.order_no', '=', 'store_order_goods.order_no')
            ->whereIn('store_order_goods.activity_goods_id', $where)
            ->where(['o.is_pay' => 1])
            ->limit(10)
            ->orderBy('store_order_goods.create_at', 'desc')
            ->select('store_order_goods.mid', 'store_order_goods.activity_goods_id', 'store_order_goods.create_at', 'store_order_goods.number')
            ->get()
            ->toArray();
        return $orderUser;
    }

    /**
     * 获取用户已购买活动商品数量与活动商品id(及时达)
     * @param int $mid
     * @param array $activity_goods_id
     * @return array
     */
    public function alreadyActivityBlurb(int $mid, array $activity_goods_id)
    {
        return OrderGoodsModel::query()->from('store_order_goods as g')->join('store_order as o', 'o.order_no', '=', 'g.order_no')
            ->whereIn('o.status', [1, 2, 3, 4, 6, 7, 8])
            ->where(['o.mid' => $mid,'o.order_source'=>0])
            ->whereIn('g.activity_goods_id',$activity_goods_id)
            ->groupBy(['g.activity_goods_id'])
            ->selectRaw('sum(g.number - g.refund_number - g.shop_refund_number) as num,activity_goods_id')
            ->get()
            ->toArray();
    }

    /**
     * 普通次日达商品用户当天已购买量(次日达)
     * @param int $mid
     * @param array $goods_id
     * @return array
     */
    public function tomorrowBlurbNum(int $mid, array $goods_id)
    {
        return OrderModel::query()->from('store_order as o')->join('store_order_goods as g', 'o.order_no', '=', 'g.order_no')
            ->whereIn('o.status', [1, 2, 3, 4, 6, 7, 8])
            ->where(['o.mid' => $mid,'o.order_source'=>1])
            ->where(['g.group_id' => 0])
            ->whereIn('g.goods_id',$goods_id)
            ->whereBetween('o.pay_at', [date('Y-m-d'), date('Y-m-d 23:59:59')])
            ->groupBy(['g.goods_id'])
            ->selectRaw('sum(g.number - g.refund_number - g.shop_refund_number) as num,goods_id')
            ->get()->toArray();
    }

    /**
     * 及时达代客下单确认订单
     * @param $param
     * @return array
     */
    public function confirmEntrustJsdOrder($param): array
    {
        $shop_id = (int)$param['shop_id'];
        $result = $this->shopService->getShopCondition($shop_id, (int)$param['order_type'],(int)$param['deal_type'],(int) $param['address_id']);
        if ($result['code']) {
            return $this->error($result['code']);
        }
        $entrustInfo = EntrustOrderModel::query()
            -> where('id', $param['entrust_id'])
            -> first(['id', 'shop_id', 'amount', 'dis_amount', 'discount', 'status', 'share', 'order_source', 'created_at', 'phone']);
        if(!$entrustInfo) return ['code' => ErrorCode::NOT_EXIST];
        $expTime = $this -> getEntrustExpTime($entrustInfo -> share);
        $checkTime = $this -> checkEntrustTime($expTime);
        if(!$checkTime){
            return ['code'  => ErrorCode::LINK_EXPIRED];
        }
        $goodsInfo = EntrustOrderGoodsModel::query() -> where('entrust_order_id', $entrustInfo -> id) -> get() -> toArray();
        foreach($goodsInfo as $key => $val){
            $goodsInfo[$key]['goods_num'] = $val['number'];
        }

        $cartList = $goodsInfo;
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        //及时达普通商品
        $res = $this->checkCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];
        //及时达限购商品
        $quota = $this->checkCartGoodsQuota($shop_id,$cartList,(int)$param['mid'],$redis);
        $quotaCartList = $quota['cartList'];
        $cartList = array_merge($generalCartList,$quotaCartList);
        if (empty($cartList)) {
            return $this->error(ErrorCode::ENTRUST_NULL);
        }
        // 与后续统一字段名称
        foreach ($cartList as $k => $v) {
            $cartList[$k]['price_selling'] = $cartList[$k]['dis_unit_price'];
        }
        $param['entrust_phone'] = $entrustInfo -> phone ?? '';
        $param['entrust_discount'] = $entrustInfo -> discount ?? 0;
        $res = $this->saveJsdOrder($cartList, $param, $shop_id);
        return $res;
    }

    /**
     * 及时达写入订单
     * @param array $cartList
     * @param array $param
     * @param int $shop_id
     * @return array
     */
    public function saveJsdOrder(array $cartList, array $param, int $shop_id)
    {
        $orderGoodsMoney = $orderGoodsNum = $goodsTrueDiscount = 0;
        foreach ($cartList as $k => $v) {
            if($v['price_selling']<=0){
                return ['code' => ErrorCode::GOODS_SELL_OUT, 'msg' => '商品信息异常'];
            }
            if($v['group_id']==Stakeholder::GROUP_ID_2 && $param['pay_type']==Stakeholder::PAYMENT_METHOD_WECHAT){
                return ['code' => ErrorCode::ORDER_PAY_TYPE_ERROE, 'msg' => '会员商品只能选择余额支付'];
            }
            $orderGoodsMoney += bcmul((string)$cartList[$k]['dis_subtotal'], 100, 2);  // 优惠后商品价格（分）
            $orderGoodsNum += $cartList[$k]['goods_num'];  // 商品数量
            $goodsTrueDiscount += bcsub((string)$cartList[$k]['subtotal'] * 100, (string)$cartList[$k]['dis_subtotal'] * 100, 2); // 商品优惠（分）
        }
        if (!empty($param['coupon'])) {
            if (empty($param['payKey'])) {
                return ['code' => ErrorCode::SYSTEM_INVALID, 'msg' => '缺少payKey参数'];
            }
            $coupon = json_decode($param['coupon'], true);
            $cut = (float)array_sum(array_column($coupon, 'deductMoney')); // 优惠的总金额 单位分
            $coupon_info = json_encode(['payKey' => $param['payKey'], 'coupon' => $param['coupon']]);
            $coupon_status = 1;

            // 使用运费券的情况
            $couponFreight = [];
            foreach ($coupon as $k => $v) {
                // 运费券
                if ($v['apply_type'] == 4) {
                    array_push($couponFreight, $v);
                }
            }
            if (!empty($couponFreight) && $param['deal_type'] == self::ORDER_DEAL_TYPE_1) {
                // 优惠的运费金额
                $coupon_freight_cut = (float)array_sum(array_column($couponFreight, 'deductMoney'));//单位分
                $coupon_freight = json_encode($couponFreight);
                $goods_cut = bcsub((string)$cut, (string)$coupon_freight_cut, 2); // 商品优惠金额
                $orderGoodsMoney = bcsub((string)$orderGoodsMoney, (string)$goods_cut, 2);
                // 运费是否优惠完
                $freight_price = bcsub((string)($param['freight_price'] * 100), (string)$coupon_freight_cut, 2);
                $totalPrice = bcadd((string)$orderGoodsMoney, (string)$freight_price, 2);
            } else {
                // 没有运费券, 优惠的总金额就是商品优惠金额
                $orderGoodsMoney = bcsub((string)$orderGoodsMoney, (string)$cut, 2);
                $totalPrice = $param['deal_type'] == self::ORDER_DEAL_TYPE_1 ? bcadd((string)$orderGoodsMoney, (string)($param['freight_price'] * 100), 2) : $orderGoodsMoney;
            }
        } else {
            $totalPrice = $param['deal_type'] == self::ORDER_DEAL_TYPE_1 ? bcadd((string)$orderGoodsMoney, (string)($param['freight_price'] * 100), 2) : $orderGoodsMoney;
        }
        if (bccomp((string)($param['total_price'] * 100), (string)$totalPrice, 2)) {
            return ['code' => ErrorCode::ORDER_PRICE_ERROR];
        }
        /***************************************************************************************/
        $orderNo = self::generateOrderNo($shop_id);
        $orderGoodsInsertData = $orderExpressInsertData = [];
        $userInfo = $this->memberService->findFirst(['mid' => $param['mid']],['mid', 'openid', 'phone']);
        $datetime = date('Y-m-d H:i:s');
        preg_match("/[0-9]{1,}:[0-9]{1,}/",$param['appointment_time'],$match);
        $appointment_date = $match?date('Y-m-d ').$match[0]:'';
        $orderData = [
            'mid' => $userInfo['mid'],
            'openid' => $userInfo['openid'],
            'order_phone' => $userInfo['phone'],
            'order_no' => $orderNo,
            'activity_id' => $param['activity_id'] ?? 0,
            'activity_type' => $param['activity_type'] ?? 0,
            'shop_id' => $shop_id,
            'deal_type' => $param['deal_type'],
            'goods_price' => bcdiv((string)$orderGoodsMoney, '100', 2),
            'freight_price' => $param['deal_type'] == self::ORDER_DEAL_TYPE_1 ? ($param['freight_price'] ?? 0.00) : 0.00,
            'total_price' => bcdiv((string)$totalPrice, '100', 2),
            'pay_type' => $param['pay_type'],
            'memo' => $param['memo'],
            'order_goods_num' => $orderGoodsNum,
            'order_type' => $param['order_type'],
            'appointment_time' => $param['appointment_time'],
            'appointment_date' => $appointment_date,
            'order_source' => $param['order_source'] ?? 0,
            'order_type_status' => $param['order_type'] == self::ORDER_TYPE_0 ? 0 : ($param['order_type'] == self::ORDER_TYPE_2 ? 2 : 0),
            'serial_num' => $this->orderRepository::getToDayOrderSerialNumByShopId($shop_id),
            'create_at' => $datetime,
            'coupon_info' => $coupon_info ?? '', // 券码
            'coupon_cut' =>  isset($cut) && !empty($cut)  ?bcdiv((string)$cut, '100', 2):0,          // 优惠金额
            'coupon_status' => $coupon_status ?? 0,  //是否使用优惠券,0未使用,1使用
            'coupon_freight' => isset($coupon_freight) && !empty($coupon_freight) ? bcdiv((string)$coupon_freight, '100', 2) : '',
            'coupon_freight_cut' => isset($coupon_freight_cut) && !empty($coupon_freight_cut) ? bcdiv((string)$coupon_freight_cut, '100', 2) : 0,
            'platform_type' => 3,
            'entrust_phone' => $param['entrust_phone'],
            'entrust_order_id' => $param['entrust_id'],
            'entrust_discount' => $param['entrust_discount'],
        ];
        if ($param['deal_type'] == self::ORDER_DEAL_TYPE_1) {
            $orderData['address_id'] = $param['address_id'];
            $orderExpressInsertData = [
                'mid' => $userInfo['mid'],
                'shop_id' => $param['shop_id'],
                'order_no' => $orderNo,
                'create_at' => $datetime,
            ];
        } else {
            $writeOffCode = Random::character(8);
            $orderData['write_off_code'] = $writeOffCode;
        }
        $goodsIds = array_column($cartList, 'goods_id');
        $goodsList = $this->goodsService->getGoodsLsy($goodsIds,['id', 'wx_crm_code', 'kz_goods_id', 'kz_type_id', 'cate_id', 'crd_cate_id', 'lsy_goods_name', 'lsy_unit_name', 'lsy_class_name']);
        $goodsListById = array_column($goodsList, null, 'id');

        foreach ($cartList as $arr) {
            $kz_goods_id = !empty($goodsListById[$arr['goods_id']]['kz_goods_id']) ? $goodsListById[$arr['goods_id']]['kz_goods_id'] : $arr['goods_id'];
            $orderGoodsInsertData[] = [
                'mid' => $userInfo['mid'],
                'shop_id' => $param['shop_id'],
                'order_no' => $orderNo,
                'goods_id' => $arr['goods_id'],
                'cate_id' =>$goodsListById[$arr['goods_id']]['cate_id'] ?? 0,
                'activity_goods_id' => $arr['activity_goods_id'] ?? 0,
                'itemCode' => $goodsListById[$arr['goods_id']]['wx_crm_code'] ?? 0,
                'kz_goods_id' => $kz_goods_id,
                'kz_type_id' => $goodsListById[$arr['goods_id']]['kz_type_id'] ?? 0,
                'group_id' => $arr['group_id'],
                'goods_title' => $arr['title'],
                'goods_spec' => $arr['goods_spec'],
                'goods_logo' => $arr['logo'],
                'selling_price' => $arr['price_selling'],
                'market_price' => $arr['price_market'],
                'number' => $arr['goods_num'],
                'crd_cate_id'=>$goodsListById[$arr['goods_id']]['crd_cate_id']??0,
                'lsy_goods_name'=>$goodsListById[$arr['goods_id']]['lsy_goods_name'],
                'lsy_unit_name'=>$goodsListById[$arr['goods_id']]['lsy_unit_name'],
                'lsy_class_name'=>$goodsListById[$arr['goods_id']]['lsy_class_name'],
                'create_at' => $datetime,
                'kz_self_num'=> $arr['kz_self_num']
            ];
        }
        $res =  $this->orderRepository->saveEntrustOrder((int)$param['mid'],$orderData,$orderGoodsInsertData,$param,self::ORDER_SOURCE_0,$orderNo,$orderExpressInsertData);
        return $res;
    }

    /**
     * 次日达确认订单
     * @param $param
     * @return array
     */
    public function confirmEntrustCrdOrder($param)
    {
        $shop_id = (int)$param['shop_id'];
        $mid = (int)$param['mid'];
        if(!$this->shopService->getShopInfobyShopIds([$shop_id],['shop_id'])->toArray()){
            return $this->error(ErrorCode::SHOP_STATUS_CLOSE);
        }
        $entrustInfo = EntrustOrderModel::query()
            -> where('id', $param['entrust_id'])
            -> first(['id', 'shop_id', 'amount', 'dis_amount', 'discount', 'status', 'share', 'order_source', 'created_at', 'phone']);
        if(!$entrustInfo) return ['code' => ErrorCode::NOT_EXIST];
        $expTime = $this -> getEntrustExpTime($entrustInfo -> share);
        $checkTime = $this -> checkEntrustTime($expTime);
        if(!$checkTime){
            return ['code'  => ErrorCode::LINK_EXPIRED];
        }
        $goodsInfo = EntrustOrderGoodsModel::query() -> where('entrust_order_id', $entrustInfo -> id) -> get() -> toArray();
        foreach($goodsInfo as $key => $val){
            $goodsInfo[$key]['goods_num'] = $val['number'];
        }

        $cartList = $goodsInfo;
        $redis = $this->container->get(RedisFactory::class)->get('resource');
        $res = $this->checkCrdCartGoods($shop_id,$cartList,$redis);
        $generalCartList = $res['cartList'];
        foreach ($generalCartList as $k => $v) {
            $cartRes = CrdCartService::is_overflow($generalCartList[$k]['goods_num'],$mid,$generalCartList[$k]['goods_id']);
            if($cartRes){
                return $this->error(30005,$generalCartList[$k]['title'].'每人每天限购'.$generalCartList[$k]['limite_num_per_day'].''.'件');//每人每天限购
            }
            if(empty($generalCartList[$k]['goods_num'])){
                return $this->error(ErrorCode::GOODS_SELL_OUT_PART, '商品信息异常:'.$v['title']);
            }
        }
        $seckill = $this->checkCrdCartGoodsSeckill($shop_id,$cartList,$mid,$redis);
        $seckillCartList = $seckill['cartList'];
        $cartList = array_merge($seckillCartList,$generalCartList);
        if (empty($cartList)) {
            return $this->error(ErrorCode::CART_NULL);
        }
        // 与后续统一字段名称
        foreach ($cartList as $k => $v) {
            $cartList[$k]['price_selling'] = $cartList[$k]['dis_unit_price'];
        }
        $param['entrust_phone'] = $entrustInfo -> phone ?? '';
        $param['entrust_discount'] = $entrustInfo -> discount ?? 0;
        $res = $this->saveCrdOrder($cartList, $param,$shop_id);
        return $res;
    }

    /**
     * 次日达订单写入
     * @param array $cartList
     * @param array $param
     * @param int $shop_id
     * @return array
     */
    public function saveCrdOrder(array $cartList, array $param, int $shop_id): array
    {
        $orderGoodsMoney = $orderGoodsNum = $commission = $goodsTrueDiscount = 0;
        $orderType = self::ORDER_TYPE_8;
        $activity_id = 0;
        $activityType =0;
        foreach ($cartList as $arr) {
            if($arr['group_id']==Stakeholder::GROUP_ID_4){
                $orderType = self::ORDER_TYPE_9;
            }
            if ($arr['price_selling'] <= 0) {
                return ['code' => ErrorCode::GOODS_SELL_OUT, 'msg' => '商品信息异常:'.$arr['title']];
            }
            $orderGoodsMoney += bcmul((string)$arr['dis_subtotal'], 100, 2);
            $commission +=$arr['commission']? bcmul((string)$arr['goods_num'], (string)($arr['commission']*100), 2):0;
            $orderGoodsNum += $arr['goods_num'];
            $goodsTrueDiscount += bcsub((string)$arr['subtotal'] * 100, (string)$arr['dis_subtotal'] * 100, 2);
        }

        $coupon_status = 0;
        $coupon_info = '';
        $cut =0;
        if (!empty($param['coupon'])) {
            if (empty($param['payKey'])) {
                return ['code' => ErrorCode::SYSTEM_INVALID, 'msg' => '缺少payKey参数'];
            }
            $coupon = json_decode($param['coupon'], true);
            $cut = (float) array_sum(array_column($coupon, 'deductMoney'));
            // 优惠的总金额 单位分
            $coupon_info = json_encode(['payKey' => $param['payKey'], 'coupon' => $param['coupon']]);
            $coupon_status = 1;
            $orderGoodsMoney = bcsub((string)$orderGoodsMoney, (string)$cut, 2);
        }

        $totalPrice = $orderGoodsMoney;
//        $finalPrice = bcsub((string)$totalPrice, (string)$param['entrust_discount'] * 100, 2);
        if (bccomp((string)($param['total_price'] * 100), (string)$totalPrice, 2)) {
            return ['code' => ErrorCode::ORDER_PRICE_ERROR];
        }

        /***************************************************************************************/

        $orderNo = self::generateOrderNo($shop_id);
        $orderGoodsInsertData = [];
        $userInfo = $this->memberService->findFirst(['mid' => $param['mid']],['mid', 'openid', 'phone']);
        $datetime = date('Y-m-d H:i:s');
        preg_match("/[0-9]{1,}-[0-9]{1,}\s[0-9]{1,}:[0-9]{1,}/",$param['appointment_time'],$match);
        $appointment_date =$match? date('Y-').$match[0]:'';
        $param['leader_id'] = $param['leader_id'] ?? 0;
        $orderData = [
            'mid' => $userInfo['mid'],
            'openid' => $userInfo['openid'],
            'order_phone' => $userInfo['phone'],
            'order_no' => $orderNo,
            'activity_id' => $activity_id,
            'activity_type' => $activityType,
            'shop_id' => $shop_id,
            'deal_type' => self::ORDER_TYPE_2,
            'goods_price' => bcdiv((string)$totalPrice, '100', 2),
            'total_price' => bcdiv((string)$totalPrice, '100', 2),
            'pay_type' => $param['pay_type'],
            'memo' => $param['memo'],
            'order_goods_num' => $orderGoodsNum,
            'order_type' => $orderType,
            'appointment_time' => $param['appointment_time'],
            'appointment_date' => $appointment_date,
            'order_source' => self::ORDER_SOURCE_1,//次日达
            'order_type_status' => 2,
            'serial_num' => $this->orderRepository::getToDayOrderSerialNumByShopId($shop_id),
            'create_at' => $datetime,
            'coupon_info' => $coupon_info, // 券码
            'coupon_cut' => $cut?bcdiv((string)$cut, '100', 2):0, // 优惠金额
            'coupon_status' => $coupon_status,  //是否使用优惠券,0未使用,1使用
            'coupon_freight' => '',
            'coupon_freight_cut' => 0,
            'order_commission' => bcdiv((string)$commission, '100', 2),
            'leader_id' => $param['leader_id'],
            'platform_type' => 3,
            'entrust_phone' => $param['entrust_phone'],
            'entrust_order_id' => $param['entrust_id'],
//            'entrust_discount' => bcdiv((string)$goodsTrueDiscount, 100, 2),
            'entrust_discount' => $param['entrust_discount'],
        ];

        $writeOffCode = Random::character(8);
        $orderData['write_off_code'] = $writeOffCode;
        $goodsIds = array_column($cartList, 'goods_id');

        $goodsList = $this->goodsService->getGoodsLsy($goodsIds,['id', 'wx_crm_code', 'kz_goods_id', 'kz_type_id', 'cate_id', 'crd_cate_id', 'lsy_goods_name', 'lsy_unit_name', 'lsy_class_name']);
        $goodsListById = array_column($goodsList, null, 'id');
        foreach ($cartList as $arr) {
            $kz_goods_id = !empty($goodsListById[$arr['goods_id']]['kz_goods_id']) ? $goodsListById[$arr['goods_id']]['kz_goods_id'] : $arr['goods_id'];
            $orderGoodsInsertData[] = [
                'mid' => $userInfo['mid'],
                'shop_id' => $param['shop_id'],
                'order_no' => $orderNo,
                'goods_id' => $arr['goods_id'],
                'cate_id' => $goodsListById[$arr['goods_id']]['cate_id'] ?? 0,
                'activity_goods_id' => $arr['activity_goods_id'] ?? 0,
                'activity_id' => $arr['activityID']??0,
                'itemCode' => $goodsListById[$arr['goods_id']]['wx_crm_code'] ?? 0,
                'kz_goods_id' => $kz_goods_id,
                'kz_type_id' => $goodsListById[$arr['goods_id']]['kz_type_id'] ?? 0,
                'group_id' => $arr['group_id'],
                'goods_title' => $arr['title'],
                'goods_spec' => $arr['goods_spec'],
                'goods_logo' => $arr['logo'],
                'selling_price' => $arr['price_selling'],
                'market_price' => $arr['price_market'],
                'cost_price' => $arr['cost_price'] ?? 0.00,
                'number' => $arr['goods_num'],
                'commission' => $arr['commission'] ?? 0,
                'crd_cate_id'=>$goodsListById[$arr['goods_id']]['crd_cate_id'],
                'lsy_goods_name'=>$goodsListById[$arr['goods_id']]['lsy_goods_name'],
                'lsy_unit_name'=>$goodsListById[$arr['goods_id']]['lsy_unit_name'],
                'lsy_class_name'=>$goodsListById[$arr['goods_id']]['lsy_class_name'],
                'create_at' => $datetime,
//                'kz_self_num'=>'xp'.Random::character(8)
                 'kz_self_num'=>$arr['kz_self_num']
            ];
        }
        $res =  $this->orderRepository->saveEntrustOrder((int)$param['mid'],$orderData,$orderGoodsInsertData,$param,self::ORDER_SOURCE_1,$orderNo,[]);
        return $res;
    }

    /**
     * @param int $mid
     * @param int $perpage
     * @return \Hyperf\Contract\LengthAwarePaginatorInterface
     * @author ran
     * @date 2021-03-26 20:32
     * mailbox 466180170@qq.com
     */
    public function getInviteOrder(int $mid, int $perpage){
        return OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->leftJoin('store_goods_list as gl', 'og.goods_id', '=', 'gl.goods_id')
            ->leftJoin('store_activity_goods as acg', 'og.activity_goods_id', '=', 'acg.id')
            ->with(['friendOrder' => function($query) {
                $query->select(['store_order.free_parent_order_no','store_order.order_no','store_order.mid',
                    'store_order.status','store_order.create_at','member.nickname','member.face_url','og.goods_title'])
                    ->leftJoin('store_order_goods as og', 'store_order.order_no', '=', 'og.order_no')
                    ->leftJoin('store_member as member', 'member.mid', '=', 'store_order.mid');
            }])
            ->select(['og.order_no','og.goods_id','og.goods_title','og.goods_logo','order.pay_at','order.is_freed',
                'order.free_num','order.free_step','order.free_activation_time','order.activity_id','og.activity_goods_id',
                'gl.goods_pick_time','acg.need_invited_num','acg.price_selling','acg.free_num as free_success_num'])
            ->where([
                'order.mid' => $mid,
                'order.order_source' => Stakeholder::NEXT_DAY_ORDER,
                'order.order_type' => Stakeholder::ORDER_TYPE_FREE,
                'order.is_pay' => Stakeholder::ORDER_PAID
            ])
            ->latest('order.create_at')
            ->paginate($perpage);
    }

    /**
     * @param int $mid
     * @param string $order_no
     * @return array
     * @author ran
     * @date 2021-03-26 20:32
     * mailbox 466180170@qq.com
     */
    public function restartInvite(int $mid, string $order_no){
        try {
            $where = ['order_no' => $order_no, 'mid' => $mid];
            $order = OrderModel::query()->where($where)->first();
            $act = ActivityModel::query()->where('activityID', $order->activity_id)->first();
            $activity_prams = json_decode($act['activity_prams'], true);
            $second_invite_time = $activity_prams['second_invite_time'];
            $free_activation_time = date('Y-m-d H:i:s');
            $order->is_freed = 0;
            $order->free_num = 2;
            $order->free_step = 1;
            $order->free_activation_time = $free_activation_time;
            $order->save();
            $countdown = $second_invite_time * 3600;
        }catch (\Exception $e){
            return ['code' => 0, 'errorCode' => ErrorCode::SYSTEM_INVALID, 'msg' => $e->getMessage()];
        }
        $this->freeMiniService->freeOrderStatus($order_no,2);
        return ['code' => 1, 'msg' => '激活成功', 'data' => ['free_step' => 1, 'countdown' => $countdown]];
    }

    /**
     * @param int $mid
     * @param int $act_goods_id
     * @param string $free_parent_order_no
     * @return array
     * @author ran
     * @date 2021-03-26 20:32
     * mailbox 466180170@qq.com
     */
    public function inviteGoodsDetail(int $mid, int $act_goods_id, string $free_parent_order_no){
        // 校验活动时间
        if($act_goods_id == 0 and !empty($free_parent_order_no)) {
            $order = OrderModel::query()
                ->from('store_order as order')
                ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
                ->leftJoin('store_member as memb', 'order.mid', '=', 'memb.mid')
                ->leftJoin('store_shop as shop', 'order.shop_id', '=', 'shop.shop_id')
                ->where(['order.order_no' => $free_parent_order_no])
                ->first(['og.activity_goods_id','order.activity_id','shop.shop_id','shop.shop_name','shop.shop_tel',
                    'shop.address as shop_address','shop.shop_desc','shop.longitude','shop.latitude','memb.nickname']);
            $end = ActivityModel::query()->where('activityID',$order->activity_id)->value('end_date');
            if (time() >= strtotime($end)) return ['code' => 0, 'errorCode' => ErrorCode::NOT_EXIST, 'msg' => '活动已结束'];
            //是否已助力
            $self_order = OrderModel::query()
                ->where(['free_parent_order_no' => $free_parent_order_no,'mid' => $mid])
                ->first(['is_pay','status']);
            $act_goods_id = $order->activity_goods_id;
        }
        $detail = ActivityGoodsModel::query()
            ->from('store_activity_goods as acg')
            ->leftJoin('store_activity as act','acg.activityID','=','act.activityID')
            ->leftJoin('store_goods as goods','acg.goods_id','=','goods.id')
            ->leftJoin('store_goods_list as gl','acg.goods_id','=','gl.goods_id')
            ->select(['acg.goods_id','acg.goods_title','acg.goods_logo','acg.goods_spec','acg.costprice','acg.price_selling',
                'acg.need_invited_num','acg.stock','acg.spell_num','acg.free_num','goods.image','goods.content','gl.goods_pick_time',
                'act.activity_prams','act.activityID as activity_id','acg.id as activity_goods_id'])
            ->where(['acg.id'=>$act_goods_id])
            ->first();
        if ($detail){
            $count = OrderGoodsModel::query()
                ->from('store_order_goods as og')
                ->leftJoin('store_order as order', 'og.order_no', '=', 'order.order_no')
                ->where(['order.activity_id' => $detail->activity_id,'order.order_type' => Stakeholder::ORDER_TYPE_FREE,'og.activity_goods_id' => $act_goods_id])
                ->whereIn('order.is_freed', [2,4])
                ->count();
            $activity_prams = json_decode($detail->activity_prams, true);
            $takeDate = $this->getOverNightTakeDate();
            $detail->free_success_number = $count + $detail->free_num;
            $detail->image = explode('|', $detail->image);
            $detail->share_image = $activity_prams['share_image'];
            $detail->share_text = $activity_prams['share_text'];
            $detail->goods_pick_time = $takeDate . ' ' . substr($detail->goods_pick_time, 0, 5);
            if (isset($order)){
                $detail->shop_id = $order->shop_id;
                $detail->shop_name = $order->shop_name;
                $detail->shop_tel = $order->shop_tel;
                $detail->shop_address = $order->shop_address;
                $detail->shop_desc = $order->shop_desc;
                $detail->longitude = $order->longitude;
                $detail->latitude = $order->latitude;

                $detail->free_parent_order_no = $free_parent_order_no;
                $detail->sharer_name = $order->nickname;
                $detail->is_pay = 0;
                if ($self_order) $detail->is_pay = ($self_order->is_pay == 1 and !in_array($self_order->status, [5,7])) ? 1:0;
            }
            unset($detail->activity_prams);
        }
        return ['code' => 1, 'msg' => '获取详情成功', 'data' => $detail];
    }

    /**
     * @param object $order
     * @return array
     * @author ran
     * @date 2021-03-26 20:31
     * mailbox 466180170@qq.com
     */
    public function freeInviteDetail(object $order){
        $activity_prams = ActivityModel::query()
                ->where('activityID', $order->activity_id)
                ->value('activity_prams')??[];
        $det = OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->leftJoin('store_member as member', 'member.mid', '=', 'order.mid')
            ->select(['member.nickname','member.face_url','og.goods_title','order.create_at','order.status'])
            ->where(['order.free_parent_order_no' => $order->order_no])
            ->latest('order.create_at')
            ->get();
        $act_info_arr = json_decode($activity_prams,true);
        $pay_time = strtotime($order->pay_at);
        $now = time();
        $countdown = 0;
        if ($order->is_freed == 0 and $order->free_num == 1 and in_array($order->free_step, [1,6])) {
            // 邀请中 邀请好友
            $countdown = $pay_time + $act_info_arr['first_invite_time']*3600 - $now;
        }
        if ($order->is_freed == 1 and $order->free_num == 1 and $order->free_step == 2) {
            // 重新激活 激活倒计时
            $countdown = $pay_time + ($act_info_arr['second_activation']+$act_info_arr['first_invite_time']) * 3600 - $now;
        }
        if ($order->is_freed == 0 and $order->free_num == 2 and $order->free_step == 1) {
            // 二次邀请中 邀请好友
            $countdown = strtotime($order->free_activation_time) + $act_info_arr['second_invite_time']*3600 - $now;
        }

        return ['countdown' => $countdown > 0 ? $countdown:0, 'list'=>$det,];
    }

    public function freeResultDetail(object $order, array $invite, $act){
        // 退款成功
        if ($order->is_freed == 4){
            $refund = FreeOrderRefund::where(['order_no'=>$order->order_no])->first(['refund_no','refund_money','created_at']);
            $ret = [
                'refund' => [
                    'refund_no' => $refund->refund_no ?? '',
                    'refund_money' => $refund->refund_money ?? 0,
                    'refund_at' => isset($refund->created_at) ? Carbon::createFromTimestamp(strtotime($refund->created_at))->toDateTimeString() : ''
                ]
            ];
        }
        if ( in_array($order->is_freed, [1,3]) ){
            if ( time() > strtotime($act->end_date) ) {
                $step = 'off';
                $reason = '很遗憾，您未在规定时间内邀请好友下单成功，您的免单彻底失败了…';
            }else{
                if ($order->free_activation_time){
                    $step = 'again';
                    $reason = '很遗憾，您未在规定时间内邀请好友下单成功，您的免单彻底失败了…';
                }else{
                    $step = 'restart';
                    $reason = '很遗憾，您未在规定时间内邀请好友下单成功，您的免单失败了…';
                }
                if ($invite['list']){
                    $apply_name = [];
                    foreach ($invite['list'] as $v) if(in_array($v['status'], [5,7])) array_push($apply_name, $v['nickname']);
                    if (!empty($apply_name)) $reason = '很遗憾，您的好友'.implode('、',$apply_name).'已申请售后，正在进行退款/退货！您的邀请失败了！';
                }
            }
            if (in_array($order->status, [5,7])) $reason = '很遗憾，您已申请售后，您的免单彻底失败了…';
            $ret = ['reason'=>$reason, 'step' => $step, 'list'=>$invite['list']];
        }
        return $ret??[];
    }

    /**
     * 个人中心我的免单
     * @param int $mid
     * @return array|int|mixed
     * @author wangchenqi
     */
    public function getFreeCenter($mid)
    {
        return OrderModel::query()
            ->from('store_order as order')
            ->leftJoin('store_order_goods as og', 'order.order_no', '=', 'og.order_no')
            ->leftJoin('store_goods_list as gl', 'og.goods_id', '=', 'gl.goods_id')
            ->leftJoin('store_activity_goods as acg', 'og.activity_goods_id', '=', 'acg.id')
            ->with(['friendOrder' => function($query) {
                $query->leftJoin('store_order_goods as og', 'store_order.order_no', '=', 'og.order_no')
                    ->leftJoin('store_member as member', 'member.mid', '=', 'store_order.mid')
                    ->select(['store_order.free_parent_order_no','store_order.order_no','store_order.mid',
                        'store_order.status','store_order.create_at','member.nickname','member.face_url','og.goods_title']);
            }])
            ->select(['og.order_no','og.goods_id','og.goods_title','og.goods_logo','order.pay_at','order.is_freed',
                'order.free_num','order.free_step','order.free_activation_time','order.activity_id','og.activity_goods_id',
                'gl.goods_pick_time','acg.need_invited_num','acg.price_selling','acg.free_num as free_success_num'])
            ->where([
                'order.mid' => $mid,
                'order.order_source' => Stakeholder::NEXT_DAY_ORDER,
                'order.order_type' => Stakeholder::ORDER_TYPE_FREE,
                'order.is_pay' => Stakeholder::ORDER_PAID,
            ])
            ->latest('order.create_at')
            ->paginate(10);
    }

}
